【发布时间】: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 << "A( " << i << " )\n"; } ^ 10 : note : no known conversion for argument 1 from ‘A’ to ‘int’ 6 : note : A::A( ) A( ) { std::cout << "A()\n"; } ^ 6 : note : candidate expects 0 arguments, 1 provided抱歉,我不能在这里格式化代码;) 4.8 仍然抱怨。 clang 也是,icc 也是。我用gcc.godbolt.org 试试这个。
标签: c++ visual-studio-2013 explicit-conversion