22

考虑以下程序:

#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) 结合使用来排序“复制构造”A 作为 f 的默认参数。

两者都添加

A a;
A a1( a );

主要并将 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++ 编译代码并且输出是相同的。

4

2 回答 2

7

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

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

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

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

在这种情况下,其他 C++ 编译器(例如 GCC 和 Clang)会报告错误。

于 2013-12-19T16:55:49.303 回答