我可以将enable_if(或者是否有其他可用的技术)与模板变量一起使用。例如
typedef float Float;
typedef double Double;
template<class T>
constexpr Bool IsFloat = std::is_same_v<T, Float>;
template<class T>
constexpr Bool IsDouble = std::is_same_v<T, Double>;
template<class T>
constexpr Bool IsFloatingPoint = IsFloat<T> || IsDouble<T>;
template<class T>
using EnableIfFloatingPoint = std::enable_if_t<IsFloatingPoint<T>>;
template
<
class T,
typename = EnableIfFloatingPoint<T>
>
constexpr T Pi = T(3.1415926535897932384626433832795);
当我尝试使用 Pi<float>
时,Visual Studio 给出编译器错误,提示“模板参数太少” ,例如。
最佳答案
我建议立即使用 std::is_floating_point
而不是手动滚动您自己的浮点检测机制。此外,您还可以使用_v
后缀而不是 ::value
从 C++17 开始。
正如一些评论中提到的,在变量模板上使用 SFINAE 本身没有多大意义,但您可以实现仅允许浮点类型能够采用 Pi
值的解决方案。尝试将变量模板设置为类型 std::enable_if_t< std::is_floating_point<T>::value, T>
,当然只有在满足条件的情况下才会有推导类型。
template<class T>
using EnableIfFloatingPoint = std::enable_if_t<std::is_floating_point<T>::value, T>;
template<class T>
constexpr T Pi = EnableIfFloatingPoint<T>(3.1415926535897932384626433832795);
Pi<T>
对于整数类型 T
根本无法编译,因为
EnableIfFloatingPoint<T>
不会推导任何类型,但我不会考虑这个 SFINAE。
更好的解决方案是 constexpr
具有适当static_assert
的函数模板验证模板是否使用“正确”类型实例化的消息。
template<class T>
constexpr T Pi()
{
using is_fp = std::is_floating_point<T>;
static_assert( is_fp::value, "Pi must be instantiated with floating point types.");
return T{3.1415926535897932384626433832795};
}
关于c++ - 变量模板和 std::enable_if,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36657585/