为什么“专业辩论”必须无效?

Jon*_*Mee 5 c++ templates template-specialization enable-if template-variables

因此,在这个传奇中还有另一个问题。Guillaume Racicot足够出色,可以为我提供另一个解决方法,因此这是我基于以下问题得出的代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这个问题似乎在我的专业化会出现,当我返回一些其他的void。例如,在上面的代码中,enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>可以防止特殊化,而只需删除最后一个参数并允许enable_if返回就void可以进行特殊化。

我认为这表明了我对这里实际发生的误解。为什么必须始终使用专用类型才能void使其正常工作?

Live Example

max*_*x66 7

不确定是否了解您不了解的内容,但...

如果你写

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> };
Run Code Online (Sandbox Code Playgroud)

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

std::enable_if_tis 时启用第二个模板变量void

当你写的时候会发生什么

for(const auto i : my_temp<decltype(foo)>) 
Run Code Online (Sandbox Code Playgroud)

编译器:

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

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

3)仅找到my_temp具有两个模板参数的a ,但是第二个具有默认参数,因此

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>
Run Code Online (Sandbox Code Playgroud)

T(即vec),因此只能匹配与my_temp<vec, vec>有所不同的内容my_temp<vec, void>

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

如果您希望通过以下方式启用专业化

enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>
Run Code Online (Sandbox Code Playgroud)

你应该使用 T

// ..............................V   T! not void
template <typename T, typename = T>
constexpr details::subscript_function<T> my_temp[] = { &details::X<T>, &details::Y<T> };
Run Code Online (Sandbox Code Playgroud)

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

离题建议:更好地std::declvalstd::is_floating_point_v测试中使用;我建议

std::enable_if_t<std::is_floating_point_v<decltype(details::X(std::declval<T>()))>>
Run Code Online (Sandbox Code Playgroud)