为什么在 ctor 的参数列表中用 `decltype(x)` 替换成员 `x` 的类型会破坏 class 模板参数推导?
Why does replacing the type of the member `x` with `decltype(x)` in a ctor's argument list break class template argument deduction?
我正在尝试编写某种预处理器怪兽来制作简单的 ctors。
这与 g++ -std=c++17
一起编译:
template<typename T>
struct foo{
T x;
foo(T _x):x(_x){}
};
auto x=foo(3);
但是怪物很难知道 x
的类型,所以我尝试了这个:
template<typename T>
struct foo{
T x;
foo(decltype(x) _x):x(_x){}
};
auto x=foo(3);
失败(class template argument deduction failed
)。但无论如何 decltype(x)
只是 T
,对吧?那么为什么代码示例不相同?
你写的是一种循环逻辑。可以这样想。
编译器看到 foo(3)
。 foo
命名了一个 class 模板,因此它会尝试执行 class 模板参数推导以找出 foo
中的 T
应该是什么。
CTAD 首先从中提取所有构造函数和构建模板推导指南。您有一个构造函数,因此它的指南必须如下所示:
template<typename T> foo(decltype(foo<T>::x) _x) -> foo<T>;
为了推导出 foo
的模板参数 T
,您需要用 T
实例化 foo
...。你还没有因为弄清楚T
是什么是你首先制作这个演绎指南的原因。
这里的简短回答是因为 C++ 标准是这么说的。 decltype
不能将表达式推导为模板参数。
17.8.2.5 Deducing template arguments from a type [temp.deduct.type]
The non-deduced contexts are:
[...]
— The expression of a decltype-specifier.
您正在使用 C++17。如果你使用 decltype
来隐藏一些怪异的东西,你可能需要使用 C++17 的演绎指南来解决它。
我正在尝试编写某种预处理器怪兽来制作简单的 ctors。
这与 g++ -std=c++17
一起编译:
template<typename T>
struct foo{
T x;
foo(T _x):x(_x){}
};
auto x=foo(3);
但是怪物很难知道 x
的类型,所以我尝试了这个:
template<typename T>
struct foo{
T x;
foo(decltype(x) _x):x(_x){}
};
auto x=foo(3);
失败(class template argument deduction failed
)。但无论如何 decltype(x)
只是 T
,对吧?那么为什么代码示例不相同?
你写的是一种循环逻辑。可以这样想。
编译器看到 foo(3)
。 foo
命名了一个 class 模板,因此它会尝试执行 class 模板参数推导以找出 foo
中的 T
应该是什么。
CTAD 首先从中提取所有构造函数和构建模板推导指南。您有一个构造函数,因此它的指南必须如下所示:
template<typename T> foo(decltype(foo<T>::x) _x) -> foo<T>;
为了推导出 foo
的模板参数 T
,您需要用 T
实例化 foo
...。你还没有因为弄清楚T
是什么是你首先制作这个演绎指南的原因。
这里的简短回答是因为 C++ 标准是这么说的。 decltype
不能将表达式推导为模板参数。
17.8.2.5 Deducing template arguments from a type [temp.deduct.type]
The non-deduced contexts are:
[...]
— The expression of a decltype-specifier.
您正在使用 C++17。如果你使用 decltype
来隐藏一些怪异的东西,你可能需要使用 C++17 的演绎指南来解决它。