C++列表初始化允许多个用户定义的转换
C++ list initialization allows multiple user-defined conversions
我正在阅读这个答案,它有以下示例:
struct R {};
struct S { S(R); };
struct T {
T(const T &); //1
T(S); //2
};
void f(T);
void g(R r) {
f({r});
}
答案与旧版本的[over.best.ics]/4有关,当时看起来是这样的:
然而,当考虑构造函数或用户定义的转换函数的参数时,当在类复制初始化的第二步中为复制/移动临时对象而调用[over.match.ctor]时,通过[over.match.list]将初始值设定项列表作为单个参数传递时,或者当初始值设定项列表正好有一个元素,并且对某个类X的转换或对X的引用(可能是cv限定的(被考虑作为X的构造函数的第一个参数时,或者在所有情况下通过[over.match.copy]、[over.maatch.conv]或[over.match.ref],仅考虑标准转换序列和省略号转换序列。
在答案中,如果没有上面引用中突出显示的部分,f({r})
将是不明确的,因为它可以使用T
(1(的第一构造函数或第二构造函数(2(。
然而,尽管我尝试了很多,我还是看不出第一个构造函数(1(是如何成为一个选项的。f({r})
导致T
从{r}
的复制列表初始化。如果使用第一个构造函数,则标准允许从r
转换为构造函数的参数类型。然而,仅仅进行一次转换是不够的,因为必须进行R-->S(使用S
的转换构造函数(然后S->T(使用T
(2(的转换构造函数(。我在标准中找不到任何允许在列表初始化的强制转换中进行多个用户定义转换的内容。
我可能错过了什么。如果有人指出我的错误,我将不胜感激,如果我没有,我想知道引用该标准中突出部分的目的是什么。
引用段落的当前版本要求初始化器列表的唯一元素是初始化器列表本身,如果不是f({r})
而是f({{r}})
,这在上面的示例中是有意义的。在这种情况下,解释是正确的。
谢谢。
您的观察是正确的。即使没有强调的部分,这个例子也很好,但原因有点不同。
我在标准中找不到任何允许在列表初始化的强制转换中进行多个用户定义转换的内容。
事实上,[over.best.ics]/4正是禁止多个用户定义转换的规则。考虑调用(1(,则我们必须使用r
复制初始化类型为T
的临时对象,该对象属于"或在所有情况下由[over.match.copy]、[over.macc.conv]或[over.match.ref]"部分,因此禁止用户定义的转换(r -> const T&
和r -> S
(。因此,我们不能为(1(形成隐式转换序列,因此(2(获胜。
请注意,由于问题1758,强调的部分曾经被删除,并且由于问题2076,再次返回时带有约束"初始值设定项列表只有一个元素本身就是初始值设定值列表"。
- 仅为某些模板专用化定义转换运算符:预期类型/预期类型说明符
- 模拟返回具有多个用户定义转换的类型的方法
- 是否可以使用明确的模板参数调用模板的用户定义转换操作员
- 使用自定义转换运算符的不明确性
- C++显式积分用户定义转换
- 解决隐藏歧义的不明确用户定义转换
- 如何自定义转换模板参数
- 用户定义转换的第二个标准转换序列
- 如何将串联的定义转换为RC文件中的字符串
- 是否可以用C++编写自定义转换运算符(如“static_cast”)
- Qt4:QGraphicsScene/View和自定义转换方法
- 如何将c结构体定义转换为c++
- 如何在VS2008中将#define定义转换为字符串
- 为什么模板化的用户定义转换操作符能够确定其返回类型?
- #定义转换为LPCSTR或std::string的字符串
- 错误无效的用户定义转换
- 无效的用户定义转换错误
- 是否有方法为任何指针类型定义转换操作符
- Visual C++ 不存在从"myClass1"到"myClass1"的合适用户定义转换
- 提振.Python自定义转换器