Using Clang 3.7 on windows platform
See following code:
class A1
{
public:
A1(char* name){}
virtual ~A1() {}
private:
A1(const A1&) {}
};
class B1 : public A1
{
public:
B1(): A1(""){}
};
I get the following error:
MyFile(31): 8: error: base class 'A1' has private copy constructor
B1(): A1(""){}
^
MyFile(25): 2: note: declared private here
A1(const A1&) {}
^
Making A1 copy constructor public, eliminates the error!
What happened here?
Note: that by changing (as I should)
A1(const char* name)
I get no errors and all compile as expected
I imagine that this is just an artefact of how the diagnostics are generated.
char*
doesn't match, as you knowprivate
A1
from your ""
argument to make that workprivate
constructorsOne might argue that this is a quality of implementation issue.
Amusingly, GCC 6.1.0 (even in pedantic C++14 mode) compiles your code as originally written, spitting out only a warning for the broken literal conversion.
You cannot call the constructor A1(char* name)
using a string literal, becase a string literal is not convertible to char*
(such deprecated conversion did exist prior to c++11). Or rather, a program that does call the constructor is ill-formed, and the implementation is allowed to refuse to compile.
As such, the overload resolution looks for other alternatives. The only other potential alternative that has the same number of arguments, is the copy constructor.
For whatever reason, clang appears to prefer the implicit conversion from string literal, to A1
, thereby creating a temporary, that could be used for copy-initialization, over using the direct construction from the literal. This behaviour leads to the confusing compilation error.
Both alternatives are ill-formed, and clang appropriately warns about it: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
. The program does compile, if you set the standard mode to older than c++11 (in which case the program would be well-formed, even though it does use a deprecated conversion). Interestingly, if we disallow the conversion, then the program compiles even in the current standard mode:
class A1
{
public:
explicit A1(char* name){} // note the explicit
virtual ~A1() {}
private:
A1(const A1&) {}
};
G++ behaves differently and your program compiles fine (with the appropriate warning of course). Both compilers appear to comply to the standard in this regard.
Moral of the story: Always read the warnings as well. In this case, the warning was perfectly clear, and easy to solve, while the same bug indirectly caused an error that was not helpful in the solving of the bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With