c++ - 为什么专业化论证必须无效?
问题描述
所以这个传奇中的另一个问题。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;
}
}
当我返回除. void
例如,在上面的代码中,enable_if_t<is_floating_point_v<decltype(details::X(T()))>, T>
防止特化,而简单地删除最后一个参数并允许enable_if
返回void
允许特化。
我认为这表明我对这里真正发生的事情的误解。为什么必须始终使用专门的类型才能void
使其正常工作?
解决方案
不确定你不明白的地方,但是......
如果你写
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
) 的类型。
第二个模板变量在 is 时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::declval
在std::is_floating_point_v
测试内使用;我建议
std::enable_if_t<std::is_floating_point_v<decltype(details::X(std::declval<T>()))>>
推荐阅读
- java - 没有 WebView 的 Android 应用程序(用 JAVA 编码)是否有可能存在 XSS 漏洞(反射或存储类型)?
- jquery - preventDefault 不适用于所有浏览器/设备
- swift - 如何在不显示弹出窗口的情况下立即打印?
- typo3 - 谷歌的站点地图有问题吗?
- angular - Angular 6 - 数据更改后绑定项不更新
- python - 为什么 Eclipse PyDev 找不到现有文件?
- flutter - 让音乐应用在后台、iOS 和 Android 中保持活力?
- security - 你能利用 emscripten 编译的 Wasm 来运行任意 JavaScript 吗?
- ios - iOS - 在后台发现 BLE
- uwp - 在 Surface 平板电脑上安装的 UWP App 上打开应用程序时如何通过代码显示键盘?