2

我可以对模板变量使用 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 会给我一个编译器错误,提示“模板参数太少” 。

4

1 回答 1

3

我建议立即使用std::is_floating_point而不是手动滚动您自己的浮点检测机制。此外,您将能够使用_v后缀而不是::value自 C++17 开始。

Pi正如一些评论中提到的,在变量模板上使用 SFINAE 本身并没有多大意义,但是您可以通过尝试设置变量模板来实现只允许浮点类型能够取值的解决方案到 type 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};
}
于 2016-04-19T13:07:50.117 回答