【问题标题】:Different behavior of direct and copy initialization on MS VC++ (using user-defined conversion operators)MS VC++ 上直接和复制初始化的不同行为(使用用户定义的转换运算符)
【发布时间】:2019-12-15 05:02:09
【问题描述】:

以下代码 compiles fine 带有 g++ 9.1 和 clang 8.0.0(编译标志是 -std=c++17 -Wall -Wextra -Werror -pedantic-errors),但不带有 MSVC 19.22(编译标志为/std:c++17 /permissive-):

struct X{};

struct Bar
{
    Bar() = default;

    Bar(X){}
};

struct Foo
{
    operator X() const
    {
        return X{};
    }

    operator Bar() const
    {
        return Bar{};
    }
};

int main()
{
    Foo foo;
    [[maybe_unused]]Bar b1 = foo; // OK
    [[maybe_unused]]Bar b2(foo);  // failed
}

MSVC 编译错误:

<source>(27): error C2668: 'Bar::Bar': ambiguous call to overloaded function
<source>(8): note: could be 'Bar::Bar(Bar &&)'
<source>(7): note: or       'Bar::Bar(X)'
<source>(27): note: while trying to match the argument list '(Foo)'

这是 MSVC 中的错误吗?

【问题讨论】:

  • 在RexTester,我也收到了note: or 'Bar::Bar(const Bar &amp;)',这更有意义。
  • @PaulSanders Rextester 使用旧版本的 MSVC(与 Microsoft Visual Studio 2015 一起提供),在我使用过 MSVC 19.22(与最新的 MSVS 2019 版本 16.2 一起提供)可用。

标签: c++ initialization language-lawyer c++17 conversion-operator


【解决方案1】:

我认为这基本上是CWG 2327的一种表现形式,它处理了这个例子:

struct Cat {};
struct Dog { operator Cat(); };

Dog d;
Cat c(d);

问题的症结在于我们不允许在这种情况下保证复制省略 - 因为我们通过 Cat 的移动构造函数而不是直接通过 Dog::operator Cat() 初始化。

而且 gcc 和 clang 似乎都已经实现了问题的 intent - 即同时对构造函数和转换函数进行重载解析。

在你的例子中:

Bar b2(foo);

根据标准的字母,我们考虑构造函数(和only constructors)——它们是Bar(X)、Bar(Bar const&amp;) 和Bar(Bar&amp;&amp;)。所有这三个都是可行的,第一个是Foo::operator X() const,第二个和第三个是Foo::operator Bar() const。我们可以更喜欢Bar(Bar&amp;&amp;) 到Bar(Bar const&amp;),但我们有办法消除Bar(X) 和Bar(Bar&amp;&amp;) 之间的歧义。 MSVC 遵循正确拒绝此初始化的标准。这不是错误。

但是 CWG 2327 的精神是这应该直接调用Foo::operator Bar() const,这就是 gcc 和 clang 所做的。很难说这是他们一方的错误,因为这可能是我们真正想要发生的行为,并且很可能是将来某个时候指定的方式。

【讨论】:

  • 将其称为 gcc 和 clang 的扩展?
  • @NathanOliver 也许吧?我认为扩展就像..绝对不是编译器添加的语言的东西。就像...表达式语句当然是扩展。这更像是对核心语言问题的预解释?有点模糊。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-03
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多