c++ - 没有特定成员的类型的 SFINAE

标签 c++ templates sfinae

为什么以下代码无法编译?为具有特定成员的类型启用模板的最简洁的解决方案是什么?如果模板变量被直接用于初始化它的表达式替换,它也会编译。

#include <iostream>

template<class T>
constexpr bool is_rect = std::is_same_v<decltype(T::left, T::top, T::right, T::bottom, void()), void>;

// compiles if is_rect<T> is replaced with the expression directly, but of course it's not a solution
template<class T, std::enable_if_t<is_rect<T>, int> = 0>
void f(T)
{
    std::cout << "rect enabled\n";
}

template<class T, std::enable_if_t<std::is_arithmetic_v<T>, int> = 0>
void f(T)
{
    std::cout << "arithmetic enabled\n";
}

struct ActualType { float left, top, right, bottom; };

int main()
{   
    f(ActualType{});
    f(int{});
    return 0;
}

最佳答案

问题是 is_rect<T>始终指定为 std::enable_if_t 的模板参数作为 f() 签名的一部分, 当 T 时为无效表达式没有特定的成员。

您可以应用部分特化来制作 is_rect给出 truefalse基于类型是否具有特定成员。例如

template<class T, class = void>
constexpr bool is_rect = false;
template<class T>
constexpr bool is_rect<T, std::void_t<decltype(T::left, T::top, T::right, T::bottom)>> = true;

然后

template<class T, std::enable_if_t<is_rect<T>, int> = 0>
void f(T)
{
    std::cout << "rect enabled\n";
}

LIVE

关于c++ - 没有特定成员的类型的 SFINAE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66579140/

相关文章:

c++ - 函数模板特化生成链接错误

c++ - 如何提供用于创建静态和动态大小 vector 的通用接口(interface)?

c++ - 计算三角形网格中的法线

c++ - 对于以下情况,原型(prototype)设计模式是否是一种正确的方法 - 仅寻找创造部分?

python - Cython:通过引用传递

c++ - 检查传递给模板的函数在参数中有类

C++11:根据容器的 value_type 专门化/限制方法

c# - 如何实现具有注入(inject)功能的通用结构层次结构

c++ - 为什么 C++ 模板不会导致多重定义错误?

c++ - union 类型的模板特化