为什么专业化论证必须无效? [英] Why Must Specializing Argument be void?

查看:27
本文介绍了为什么专业化论证必须无效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个传奇中的另一个问题.Guillaume Racicot 已经足以为我提供另一种解决方法 所以这是我将基于此问题的代码:

So yet another question in this saga. Guillaume Racicot has been good enough to provide me with yet another workaround so this is the code I'll be basing this question off of:

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 之外的other 时,问题似乎出现在我的专业领域.例如,在上面的代码中,enable_if_t, T> 防止特化,同时简单地删除最后一个参数并允许 enable_if 返回 void 允许特化.

The problem seems to arise in my specialization when I return something other than void. In the code above for example, enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T> prevents specialization, while simply removing the last argument and allowing enable_if to return void allows specialization.

我认为这表明我对这里真正发生的事情的误解.为什么专用类型必须总是 void 才能工作?

I think this points to my misunderstanding of what is really happening here. Why must the specialized type always be void for this to work?

现场示例

推荐答案

不确定你不明白的东西,但是...

Not sure to understand what you don't understand but...

如果你写

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).

you have a first, main, template variable with two templates: a type and a type with a default (void).

第二个模板变量在 std::enable_if_tvoid 时启用.

The second template variable is enabled when std::enable_if_t is void.

写作时发生了什么

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

?

编译器:

1) 找到具有单个模板参数的 my_temp

1) find my_temp<decltype(foo)> that has a single template parameter

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

2) look for a matching my_temp template variable

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

3) find only a my_temp with two template parameters but the second has a default, so

4) 决定 my_temp 只能是 my_temp(或 my_temp,如果您愿意)

4) decide that my_temp<decltype(foo)> can be only my_temp<decltype(foo), void> (or my_temp<vec, void>, if you prefer)

5) 看到主 my_temp 匹配

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

6) see that the my_temp specialization doesn't matches because

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

T(即 vec),因此只能匹配与 my_temp< 不同的 my_temp;vec, void>.

is T (that is vec), so could match only my_temp<vec, vec> that is different from my_temp<vec, void>.

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

7) choose the only template variable available: the main one.

如果您希望通过

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> };

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

as default for second template type in the main template variable.

离题建议:最好在std::is_floating_point_v测试中使用std::declval;我建议

Off Topic suggestion: better use std::declval inside the std::is_floating_point_v test; I suggest

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

这篇关于为什么专业化论证必须无效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆