我正在尝试使用SFINAE重置operator T()
以在T
是基本类型时返回副本,并在T
是类时使用const引用。
在下面的示例中使用double
时,我无法删除第二次重载(std::is_class
)。
也就是说,我得到的错误是:
error: no type named ‘type’ in ‘struct std::enable_if<false, const double&>’
operator typename std::enable_if< std::is_class<T>::value, const T&>::type () const
^
我做错了什么?
#include <iostream>
#include <type_traits>
template<typename T>
struct Foo
{
operator typename std::enable_if<!std::is_class<T>::value, T >::type () const
{
return _val;
}
operator typename std::enable_if< std::is_class<T>::value, const T&>::type () const
{
return _val;
}
T _val;
};
int main()
{
Foo<double> f1;
f1._val = 0.3;
double d = f1;
std::cout << d << std::endl;
return 0;
}
答案 0 :(得分:9)
T
在您的类成员函数被实例化时已经知道,因此不会发生替换,而不是SFINAE,您会收到一个硬错误。最简单的解决方法是为这些运算符重载引入虚拟模板参数,并将其默认为T
,以便仍然可以进行类型推导。
template<typename U = T>
operator typename std::enable_if<!std::is_class<U>::value, U >::type () const
{
return _val;
}
template<typename U = T>
operator typename std::enable_if< std::is_class<U>::value, const U&>::type () const
{
return _val;
}
答案 1 :(得分:4)
虽然没有解决为什么不丢弃不正确的运算符的问题,但是为了解决手头的特定问题,即通过const ref返回类类型或通过其他人的值,可以使用std::conditional
找到解决方案。
template< bool B, class T, class F >
struct conditional;
提供成员typedef类型,如果B为真,则定义为T. 编译时间,如果B为假,则为F。
工作示例:
#include <iostream>
#include <type_traits>
template<typename T>
struct Foo
{
operator typename std::conditional<
std::is_class<T>::value, const T&, T>::type () const
{
return _val;
}
T _val;
};
int main()
{
Foo<double> f1;
f1._val = 0.3;
double d = f1;
std::cout << d << std::endl;
return 0;
}
答案 2 :(得分:-3)
您应阅读std :: enable_if
的定义模板&LT; bool B,T级= void&gt; struct enable_if;
“如果B为真,则std :: enable_if具有公共成员typedef类型,等于T;否则,没有成员typedef。”