2

I'm trying to compile the following simple code using g++ 4.9.0:

struct A {
    explicit A(int x) { }
};

struct B : public virtual A {
    using A::A;
};

int main(int argc, char** argv) {
    B b(0);
    return 0;
}

But I get the following error:

$ g++ -std=c++11 main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:10:10: error: use of deleted function ‘B::B(int)’
     B b(0);
          ^
main.cpp:6:14: note: ‘B::B(int)’ is implicitly deleted because the default definition would be ill-formed:
     using A::A;
              ^
main.cpp:6:14: error: no matching function for call to ‘A::A()’
main.cpp:6:14: note: candidates are:
main.cpp:2:14: note: A::A(int)
     explicit A(int x) { }
              ^
main.cpp:2:14: note:   candidate expects 1 argument, 0 provided
main.cpp:1:8: note: constexpr A::A(const A&)
 struct A {
        ^
main.cpp:1:8: note:   candidate expects 1 argument, 0 provided
main.cpp:1:8: note: constexpr A::A(A&&)
main.cpp:1:8: note:   candidate expects 1 argument, 0 provided

Am I doing something wrong? Is it a compiler bug?

manlio
  • 18,345
  • 14
  • 76
  • 126
orlp
  • 112,504
  • 36
  • 218
  • 315
  • hm, [clang compiles it](http://coliru.stacked-crooked.com/a/24e4b21aeab3cf4d), not gcc – quantdev Sep 03 '14 at 21:07
  • 2
    This is GCC bug [58751](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58751). – T.C. Sep 03 '14 at 21:09
  • SO related is there (and actually is the source of the gcc file report) : http://stackoverflow.com/questions/19399644/inheriting-constructors-and-virtual-base-classes – quantdev Sep 03 '14 at 21:15

2 Answers2

4

This is a GCC bug. §7.3.3 [namespace.udecl]/p3 requires that

In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined. If such a using-declaration names a constructor, the nested-name-specifier shall name a direct base class of the class being defined...

A is a direct base of B, so using A::A; is allowed.

The standard specifies that (§12.9 [class.inhctor]/p8):

An implicitly-defined inheriting constructor performs the set of initializations of the class that would be performed by a user-written inline constructor for that class with a mem-initializer-list whose only mem-initializer has a mem-initializer-id that names the base class denoted in the nested-name-specifier of the using-declaration and an expression-list as specified below, and where the compound-statement in its function body is empty (12.6.2). If that user-written constructor would be ill-formed, the program is ill-formed. Each expression in the expression-list is of the form static_cast<T&&>(p), where p is the name of the corresponding constructor parameter and T is the declared type of p.

Thus the corresponding user-written constructor is

B::B(int x) : A(static_cast<int&&>(x)) { }

which is well-formed.

T.C.
  • 133,968
  • 17
  • 288
  • 421
1

It appears to compile with clang, but not gcc (at least on my machine). Even with, gcc, however, the code compiles and works fine if you simply add a explicit A() constructor to the base class.

EDIT Apparently, as pointed out in the comment by @T.C., this is a known bug in GCC.

wolfPack88
  • 4,163
  • 4
  • 32
  • 47