【问题标题】:Visual Studio 2013 'explicit' keyword bug?Visual Studio 2013“显式”关键字错误?
【发布时间】:2013-12-10 15:16:30
【问题描述】:

考虑以下程序:

#include <iostream>

class A
{
public:
  A( ) { std::cout << "A()\n"; }

  A( A& ) = delete;

  A( int i ) { std::cout << "A( " << i << " )\n"; }

  explicit operator int( ) { std::cout << "operator int()\n"; return 42; }
};

template< typename T = A > void f( T a = A() ) {}

int main( void )
{
  f();
  return 0;
}

Visual Studio 2013 编译此代码并运行,并输出

A()
operator int()
A( 42 )

这是编译器错误吗?看起来 VS 编译器在这种情况下没有注意“显式”关键字。据我了解,VS 2013 错误地将运算符 int() 与 A(int) 结合使用来排序“copy-construct” A 作为 f 的默认参数。

都加

A a;
A a1( a );

到 main 并将 f 声明为

void f( A a = A() ) {}

不编译,VS 抱怨 A(A&) 被删除,这似乎是正确的行为。只有在函数模板默认参数的上下文中,运算符 int() 和 A(int) 的组合似乎可以替代 A( A& )。

g++ 4.7.3 不编译代码并报错:

main.cpp: In function ‘int main()’:
main.cpp:21:7: error: no matching function for call to ‘A::A(A)’
main.cpp:21:7: note: candidates are:
main.cpp:10:3: note: A::A(int)
main.cpp:10:3: note:   no known conversion for argument 1 from ‘A’ to ‘int’
main.cpp:6:3: note: A::A()
main.cpp:6:3: note:   candidate expects 0 arguments, 1 provided

去掉'explicit'使得g++编译代码和输出是一样的。

【问题讨论】:

  • explicit 应用于转换运算符(与构造函数相反)是 C++11 中的新功能。也许您使用的 VC++ 版本还没有实现该功能(或者您使用的标志可能没有启用它)?
  • msvc 允许对临时对象进行非 const 引用,如果他们因为更喜欢这种方式而选择这样做,我不会感到惊讶。
  • @JeremyRoman 该功能是在 VS 2013 中新引入的,它在最后两个示例中正常工作,所以我猜在这种情况下对显式的支持被忽略了?
  • @Mgetz 如果我让 A( A& ) = delete;或 A( A& ) {} private 代码仍然可以编译并且输出仍然相同。
  • @Mgetz: 21 : error : no matching function for call to ‘A::A( A )’ f( 42 ); ^ 21 : note : candidates are : 10 : note : A::A( int ) A( int i ) { std::cout &lt;&lt; "A( " &lt;&lt; i &lt;&lt; " )\n"; } ^ 10 : note : no known conversion for argument 1 from ‘A’ to ‘int’ 6 : note : A::A( ) A( ) { std::cout &lt;&lt; "A()\n"; } ^ 6 : note : candidate expects 0 arguments, 1 provided 抱歉,我不能在这里格式化代码;) 4.8 仍然抱怨。 clang 也是,icc 也是。我用gcc.godbolt.org 试试这个。

标签: c++ visual-studio-2013 explicit-conversion


【解决方案1】:

这绝对是 Visual C++ 中的一个错误。按标准:

12.3.2 转换函数[class.conv.fct]

2 - 转换函数可能是显式的(7.1.2),在这种情况下它是 仅被视为直接初始化的用户定义转换 (8.5) 在某些情况下 (13.3.1.4, 13.3.1.5, 13.3.1.6)。

您的示例中没有直接初始化。

GCC 和 Clang 等其他 C++ 编译器在这种情况下会报错。

【讨论】:

    【解决方案2】:
    猜你喜欢
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 2016-07-09
    • 2014-01-09
    • 2014-07-15
    相关资源
    最近更新 更多