变量模板和 std::enable_if
variable templates and std::enable_if
我可以对模板变量使用 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 给我一个编译器错误提示 "too few template arguments"。
我建议立即使用 std::is_floating_point
而不是手动滚动您自己的浮点检测机制。此外,从 C++17 开始,您将能够使用 _v
后缀而不是 ::value
。
正如一些评论中提到的,在变量模板上使用 SFINAE 本身没有多大意义,但您可以实现仅允许浮点类型能够采用 [= 的值的解决方案15=] 通过尝试将变量模板设置为类型 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
消息,用于验证该模板是使用 "correct" 类型实例化的。
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};
}
我可以对模板变量使用 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 给我一个编译器错误提示 "too few template arguments"。
我建议立即使用 std::is_floating_point
而不是手动滚动您自己的浮点检测机制。此外,从 C++17 开始,您将能够使用 _v
后缀而不是 ::value
。
正如一些评论中提到的,在变量模板上使用 SFINAE 本身没有多大意义,但您可以实现仅允许浮点类型能够采用 [= 的值的解决方案15=] 通过尝试将变量模板设置为类型 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
消息,用于验证该模板是使用 "correct" 类型实例化的。
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};
}