为什么专业化论证必须无效? [英] Why Must Specializing Argument be void?
问题描述
这个传奇中的另一个问题.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
防止特化,同时简单地删除最后一个参数并允许 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_t
为 void
时启用.
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屋!