我试图通过一个简单的示例来理解如何使用 std::enable_if
.我读完this answer ,我认为想出一个简单的例子应该不会太难。我想用 std::enable_if
在两个成员函数之间进行选择,并只允许使用其中一个。
不幸的是,以下代码无法使用 gcc 4.7 进行编译,经过数小时的尝试,我想问问你们我的错误是什么。
#include <utility>
#include <iostream>
template< class T >
class Y {
public:
template < typename = typename std::enable_if< true >::type >
T foo() {
return 10;
}
template < typename = typename std::enable_if< false >::type >
T foo() {
return 10;
}
};
int main() {
Y< double > y;
std::cout << y.foo() << std::endl;
}
gcc 报告以下问题:
% LANG=C make CXXFLAGS="-std=c++0x" enable_if
g++ -std=c++0x enable_if.cpp -o enable_if
enable_if.cpp:12:65: error: `type' in `struct std::enable_if<false>' does not name a type
enable_if.cpp:13:15: error: `template<class T> template<class> T Y::foo()' cannot be overloaded
enable_if.cpp:9:15: error: with `template<class T> template<class> T Y::foo()'
为什么g++不删除第二个成员函数的错误实例化?根据标准,std::enable_if< bool, T = void >::type
仅当 bool 模板参数为真时才存在。但为什么 g++ 不将其视为 SFINAE?我认为重载错误信息来自g++没有删除第二个成员函数的问题,认为这应该是一个重载。
最佳答案
SFINAE 仅在模板参数的参数推导中的替换使构造格式错误时才有效。没有这样的替代品。
I thought of that too and tried to use
std::is_same< T, int >::value
and! std::is_same< T, int >::value
which gives the same result.
那是因为当类模板被实例化时(当您创建类型为 Y<int>
的对象时会发生这种情况),它会实例化其所有成员声明(不一定是它们的定义/主体!)。其中还有它的成员模板。注意 T
然后是已知的,并且!std::is_same< T, int >::value
产生错误。所以它会创建一个类 Y<int>
其中包含
class Y<int> {
public:
/* instantiated from
template < typename = typename std::enable_if<
std::is_same< T, int >::value >::type >
T foo() {
return 10;
}
*/
template < typename = typename std::enable_if< true >::type >
int foo();
/* instantiated from
template < typename = typename std::enable_if<
! std::is_same< T, int >::value >::type >
T foo() {
return 10;
}
*/
template < typename = typename std::enable_if< false >::type >
int foo();
};
std::enable_if<false>::type
访问不存在的类型,因此该声明格式错误。因此您的程序无效。
您需要制作成员模板' enable_if
取决于成员模板本身的参数。那么声明是有效的,因为整个类型仍然是依赖的。当您尝试调用其中之一时,会发生其模板参数的参数推导,并且 SFINAE 会按预期发生。参见 this question以及如何做到这一点的相应答案。
关于c++ - std::enable_if 有条件地编译一个成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41222414/