C++ 使用使用成员类型别名的构造函数推断类模板参数
所以很明显,这应该是可行的:C++ 使用使用成员类型别名的构造函数推断类模板参数,c++,language-lawyer,c++17,C++,Language Lawyer,C++17,所以很明显,这应该是可行的: template<class T> struct C { using value_type = T; C(value_type); }; C c(1); // C<int> 请注意,似乎等效的显式指南不起作用,因为参数是非推断上下文: template<class T> C(typename C<T>::value_type) -> C<T>; 模板 C(typename C::va
template<class T>
struct C {
using value_type = T;
C(value_type);
};
C c(1); // C<int>
请注意,似乎等效的显式指南不起作用,因为参数是非推断上下文:
template<class T>
C(typename C<T>::value_type) -> C<T>;
模板
C(typename C::value_type)->C;
虽然至少第一个代码片段能够工作确实是可取的,但我还没有找到在当前的工作草案中真正起作用的措辞。有人知道它在哪里吗?严格来说,这不是一个答案,因为我认为实际上不存在这样的措辞。这更多的是把与这个问题相关的信息拼凑在一起
这是。在Oulu和Issaquah中关于此功能的讨论清楚地表明,其目的是查看typedefs是有效的,但是没有添加任何措辞来说明这应该如何工作-它只是。。。是目前的措辞表明,扣除指南适用于:
template<class T>
struct C {
using value_type = T;
C(value_type);
};
模板
结构C{
使用值_type=T;
C(价值型);
};
将是:
template <class T> C<T> foo(typename C<T>::value_type );
模板C foo(typename C::value\u type);
这将是一个非推断的背景和失败,但没有一个明确的演绎指南的情况下
中的示例显然旨在表明typedef应该起作用,尽管该示例中没有一个示例实际使用#1作为推断指南:
模板结构A{
使用值_type=T;
A(值_类型);/#1
A(常数A&)/#2
A(T,T,int);/#3
模板
A(int,T,U);/#4
//#5为复印件扣款候选人,A(A)
};
A x(1,2,3);//使用从非模板构造函数生成的#3
模板
A(T)->A;//#6,专业程度低于#5
A(42);//使用#6推导A,使用#1初始化
A b=A;//使用#5推导A,使用#2初始化
模板
A(A)->A;//#7,像#5一样专业
A b2=A;//使用#7推导A,使用#1初始化
我认为仔细阅读可以清楚地看出: 函数参数的类型是构造函数的类型 请注意,
C::value_type
不是一个类型,而是一个typedef名称。由于替换,构造函数参数的类型是T
,而等效的推导指南实际上是
template <class T> C(T) -> C<T>;
模板C(T)->C;
在您的示例中,使用
C::value\u type
使非推断上下文似乎存在问题,但该问题实际上并不存在,因为没有涉及推断函数参数的查找。无关:不应d(1,“C”)
抛出一个类似于为参数“T”(“int”和“char”)推断出冲突类型的错误。
?或者这里meow\t
是在一个非推断的上下文中?但是如果是,那么代码中的注释是错误的,//D
应该是//D
。否meow\u t
是t
。对,我就是这么想的。但是在d(1,'c')
中有一个int
和一个char
。为什么类型推断在这里可以工作,因为(afaik)没有执行转换?例如,这个C++1z之前的示例没有编译:再看一遍,它是t
,而不是U
。哦,是的,谢谢,我的错!不过,这并不完全是CWG2。演绎向导不是成员,由它们合成的函数/函数模板也不是原始类模板的成员。@t.C.是的,不完全是,但它在同一轨道中。我怀疑这只会增加标准中未充分保密的模板相关问题的数量。@T.C.想在std讨论中加入一些东西吗?我相信我们在Issaquah讨论中描述的方式是“这里发生了激烈的手工操作”。预期的规则是CWG2:如果您可以通过仅使用模板中的信息来确定类型是什么,那么您可以针对该类型。(换句话说,如果使用可推断类型重新声明构造函数是有效的,则可以根据该类型进行推断。但这会让您返回CWG 2以确定重新声明何时有效。)相同的参数适用于T
:“它是一个typedef名称”(请参见[temp.param]/3);它“不是一种类型”。我不明白你如何根据这个论点在这里做出原则性的区分。我明白你的观点,但这是我能从代码中得到的最接近的。使用value\u type
没有那么接近,它会导致一个问题,它看起来像是一个非推断上下文,实际上并不相关,因为不涉及查找。与其他任何情况不同,所讨论的构造函数是类模板的成员,而不是类(例如,类模板专门化)。其参数类型为T
,因为尚未提供T
的值。是的,这是一个丑陋的语言黑客。
template <class T> struct A {
using value_type = T;
A(value_type); // #1
A(const A&); // #2
A(T, T, int); // #3
template<class U>
A(int, T, U); // #4
// #5 is the copy deduction candidate, A(A)
};
A x(1, 2, 3); // uses #3, generated from a non-template constructor
template <class T>
A(T) -> A<T>; // #6, less specialized than #5
A a(42); // uses #6 to deduce A<int> and #1 to initialize
A b = a; // uses #5 to deduce A<int> and #2 to initialize
template <class T>
A(A<T>) -> A<A<T>>; // #7, as specialized as #5
A b2 = a; // uses #7 to deduce A<A<int>> and #1 to initialize
template <class T> C(T) -> C<T>;