Error: base class "A1" has a private copy constructor

Using Clang 3.7 on a Windows Platform

See the 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&) {} ^ 

Creating copy constructor A1 publicly fixes the error!

What happened here?

Note: this is a change (as I should)

 A1(const char* name) 

I get no errors and everything compiles as expected

+8
c ++ copy-constructor c ++ 11 clang
source share
2 answers

You cannot invoke the A1(char* name) constructor A1(char* name) using a string literal because the string literal cannot be converted to char* (such an obsolete conversion existed before C ++ 11). Rather, the program calling the constructor is poorly formed, and implementations are allowed to refuse compilation.

Thus, overload resolution is looking for other alternatives. The only potential alternative that has the same number of arguments is a copy constructor.

For some reason, clang seems to prefer an implicit conversion from a string literal, A1 , thereby creating a temporary one that can be used to initialize copying using a direct literal construct. This behavior leads to a confusing compilation error.

Both alternatives are poorly formed, and clang warns about it accordingly: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings] . The program will compile if you set the standard mode to an older one than C ++ 11 (in this case, the program will be well-formed, even if it uses an obsolete conversion). Interestingly, if we refuse 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 seem to conform to the standard in this regard.

Moral of the story: always read the warnings. In this case, the warning was completely clear and easy to solve, while the same error indirectly caused an error that did not help solve the problem.

+3
source share

I guess this is just an artifact about how diagnostics are generated.

  • Firstly, the search tries to find the constructor according to your "call" (this is not a call, but any)
  • The stor accepting char* does not match, as you know
  • The only other candidate is private
  • The compiler is trying to figure out if it can create a temporary A1 from your argument "" to make this work
  • In this case, again, all that can find are private constructors
  • The compiler decides to complain about it before doing anything else.

It can be argued that this is a problem with the quality of implementation.

Amusingly, GCC 6.1.0 (even in pedantic C ++ 14 mode) compiles your code as originally written , spitting out only a warning about intermittent literal conversion.

+6
source share

All Articles