Consider the following program:
#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 compiles this code and runs, with output
A()
operator int()
A( 42 )
Is this a compiler bug? It looks like the VS compiler doesn't heed the 'explicit' keyword in this context. From my understanding, VS 2013 wrongly uses operator int() in combination with A(int) to sort-of 'copy-construct' A as the default parameter for f.
Both adding
A a;
A a1( a );
to main and declaring f as
void f( A a = A() ) {}
does not compile, VS complains that A(A&) is deleted, which seems to be correct behavior. Only in the context of the function template default parameter the combination of operator int() and A(int) seem to work as a substitution for A( A& ).
g++ 4.7.3 does not compile the code and complains:
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
Removing 'explicit' makes g++ compile the code and the output is the same.
This is definitely a bug in Visual C++. According to standard:
12.3.2 Conversion functions [class.conv.fct]
2 - A conversion function may be explicit (7.1.2), in which case it is only considered as a user-defined conversion for direct-initialization (8.5) in certain contexts (13.3.1.4, 13.3.1.5, 13.3.1.6).
and there is no direct-initialization in your example.
Other C++ compilers such as GCC and Clang report an error in this case.
Brought up in the VS forum:
And reported it as a bug:
来源:https://stackoverflow.com/questions/20498142/visual-studio-2013-explicit-keyword-bug