使用 SFINAE 启用转换运算符
enable conversion operator using SFINAE
我正在尝试重载operator T()
使用 SFINAE 在 T
是基本类型时返回副本,当 T
是类时返回常量引用。
在下面的示例中使用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;
}
> 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;
}
现场演示
虽然不解决为什么不正确的运算符没有被丢弃的问题,但要解决手头的特定问题,即通过类类型的 const ref 或其他类型返回值,可以使用 std::conditional
找到解决方案。
template< bool B, class T, class F >
struct conditional;
提供成员类型定义类型,如果 B 在 编译时,或者如果 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;
}
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 构造函数和转换运算符之间的重载解析
- 分配给转换运算符失败-C++
- 转换运算符不适用于sleep_until
- 尝试使用算术运算符阻止隐式转换
- 错误 C2679:二进制"<<":未找到采用类型 'std::string_view' 的右侧操作数的运算符(或者没有可接受的转换)
- 是否可以将带有字符串化运算符的宏转换为 constexpr?
- C2678 二进制 '==':未找到采用 'Card' 类型左操作数的运算符(或者没有可接受的转换)
- 继承模板化转换运算符
- 将 OR 逻辑运算符从 C++ 转换为 Fortran
- 模板转换运算符在 clang 6 和 clang 7 之间的区别
- 如何在C++中正确重载运算符转换字符*?
- 将私有结构哈希器运算符转换为静态
- 混合类型的Boost运算符-转换和私有成员
- 如何将 c++ 运算符转换为 Java
- 运算符转换,GCC 和 clang:哪个编译器是正确的
- 将 istream 运算符>>转换为 istream getline
- 在C++中,将任意在位运算符转换为一元运算符
- 将运算符转换为 std::复杂<double>
- 为什么按位否定运算符"~"转换为 int?(从"int"转换为"无符号字符"可能会改变其值)