c++ - 为什么特化论证必须无效?

标签 c++ templates template-specialization enable-if template-variables

this saga 中的另一个问题. Guillaume Racicot已经足够好了,可以为我提供 yet another workaround所以这是我提出这个问题的代码:

struct vec
{
    double x;
    double y;
    double z;
};

namespace details
{
template <typename T>
using subscript_function = double(*)(const T&);

template <typename T>
constexpr double X(const T& param) { return param.x; }

template <typename T>
constexpr double Y(const T& param) { return param.y; }

template <typename T>
constexpr double Z(const T& param) { return param.z; }
}

template <typename T, typename = void>
constexpr details::subscript_function<T> my_temp[] = { &details::X<T>, &details::Y<T> };

template <typename T>
constexpr details::subscript_function<T> my_temp<T, enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>>[] = { &details::X<T>, &details::Y<T>, &details::Z<T> };


int main() {
    vec foo = { 1.0, 2.0, 3.0 };

    for(const auto i : my_temp<decltype(foo)>) {
        cout << (*i)(foo) << endl;
    }
}

当我返回不同于 void其他东西时,问题似乎出现在我的特化中.例如,在上面的代码中,enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>防止特化,同时简单地删除最后一个参数并允许 enable_if返回 void允许特化。

我认为这表明我对这里真正发生的事情有误解。为什么专用类型必须始终是 void这行得通吗?

Live Example

最佳答案

不确定你不明白的是什么,但是......

如果你写

template <typename T, typename = void>
constexpr details::subscript_function<T> my_temp[] = { &details::X<T>, &details::Y<T> };

template <typename T>
constexpr details::subscript_function<T> my_temp<T, enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>>[] = { &details::X<T>, &details::Y<T>, &details::Z<T> };

您有一个带有两个模板的第一个主要模板变量:一个类型和一个具有默认值的类型 (void)。

std::enable_if_t 时启用第二个模板变量是void .

当你写的时候会发生什么

for(const auto i : my_temp<decltype(foo)>) 

?

编译器:

1) 查找my_temp<decltype(foo)>有一个模板参数

2) 寻找匹配的 my_temp模板变量

3) 只找到一个my_temp有两个模板参数,但第二个有默认值,所以

4) 决定my_temp<decltype(foo)>只能是my_temp<decltype(foo), void> (或 my_temp<vec, void>,如果您愿意)

5) 看到主my_temp火柴

6) 看到 my_temp特化不匹配,因为

enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>

T (即 vec ),所以只能匹配 my_temp<vec, vec>这与 my_temp<vec, void> 不同.

7) 选择唯一可用的模板变量:主变量。

如果您希望通过

启用特化
enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>

你应该使用T

// ..............................V   T! not void
template <typename T, typename = T>
constexpr details::subscript_function<T> my_temp[] = { &details::X<T>, &details::Y<T> };

作为主模板变量中第二个模板类型的默认值。

题外话建议:更好用std::declvalstd::is_floating_point_v里面测试;我建议

std::enable_if_t<std::is_floating_point_v<decltype(details::X(std::declval<T>()))>>

关于c++ - 为什么特化论证必须无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56667847/

相关文章:

C++ 具有多个值的队列

c# - 通过 UDP 连接在 C# 中读取此 C++ 编码数据

C++ 模板二叉搜索树 - 参数列表错误

c++ - 根据模板参数生成不同大小的初始化列表

c++ - 使用默认容器,但在 priority_queue 中使用自定义比较器

c++ - 如何从 C++ 程序中的容器类中删除第一个元素?

C++检查xs :double datatype

c++ - 使用模板在类中定义静态数组

c++ - 如何专门针对特定类型的模板类方法?

c++ - c++模板中的多个类型名参数? (可变参数模板)