繁体   English   中英

为什么在初始化期间应用了用户定义的转换?

[英]Why does user-defined conversion applied during the initialization?

以下代码工作正常:

#include <iostream>

struct B
{
    operator int()
    {
        return int();
    }
};

struct A
{
    A(int, int){ std::cout << "A(int, int)" << std::endl; }
};

A a({B(), B()});

int main()
{ 
}

并产生输出:

A(int, int)

DEMO

但我不明白为什么? 标准说的是:

但是,在考虑构造函数或用户定义的转换函数的参数时,如果在类复制初始化的第二步中复制/移动临时函数时,通过13.3.1.3调用该函数,则通过13.3.1.7传递时初始化程序列表作为单个参数,或者当初始化程序列表只有一个元素并且转换为某个类X或引用(可能是cv限定的)时,X仅被视为X [...]的构造函数的第一个参数考虑标准转换序列和省略号转换序列

所以在我们的例子中,我们考虑了构造函数的参数(它是{B(), B()} )。 更确切地说,我们将initializer-list作为单个参数传递(我引用的规则中的第二个案例)。 现在,我们需要将initializer-list的第一个元素(类型B临时元素)转换为int ,唯一的方法是应用用户定义的转换( B::operator int() )。 但是,正如在规则末尾所说的那样,我引用标准转换序列和省略号转换序列 因为,该代码不应该工作,它应该抛出像A(int, int)不可行或类型的错误。

怎么了。 可能是一个错误?

措辞有缺陷,并用C ++ 14改变。 现在[over.best.ics] / 4读

但是,如果目标是

  • 构造函数的第一个参数或
  • [...]

并且构造函数或用户定义的转换函数是候选者

  • 13.3.1.3, 当参数是类拷贝初始化的第二步中的临时参数时
  • 13.3.1.4,13.3.1.5或13.3.1.6(在所有情况下),或
  • 13.3.1.7的第二阶段,当初始化列表只有一个元素,并且目标是类X的构造函数的第一个参数,并且转换为X或引用(可能是cv-qualified) X

不考虑用户定义的转换序列。 [ 注意:这些规则阻止在重载解析期间应用多个用户定义的转换,从而避免无限递归。 - 结束说明 ]

B()int的转换不在此范围内 - 粗体短语仅适用于在复制初始化期间对临时引用的绑定。
但是, Clang根据以上内容拒绝了此示例代码

class A;

struct B
{
    operator A();
};

struct A
{
    A(A const&){}
};

A a{B()};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM