c++ - 变量模板和 std::enable_if

标签 c++ enable-if variable-templates

我可以将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/

相关文章:

c++ - 我可以使用一个变量模板来声明另一个变量模板吗?

c++ - 将常量定义为函数会导致 header = 坏主意?

c++ - 静态数组访问冲突?

java - 检测数组中的空引用

c++ - 以下代码之间有什么区别,为什么一个有效而另一个无效?

使用概念具有特定值类型的任何容器的 C++ 迭代器

c++ - 是否有任何理由不将 assert() 包装在解析为 gcc 中的 __builtin_unreachable() 的宏中?

c++ - 非模板化成员函数的 enable_if 用法

c++ - 变量模板的部分特化

c++ - 在 Class 范围内声明时,应如何在 C++14 中引用变量模板?