vendredi 2 décembre 2016

Constructor inheritance and direct member initialisation

I am trying to use a combination of the C++ 11 direct data member initialisation and the "using" syntax to inherit the constructors of a base class. Now with gcc 5.4.0 (on Ubuntu 16.04) I observe a strange error, if the data member type has no default constructor. It is probably easiest to understand when looking on the following minimal example:

#include <iostream>

struct Foo {
  Foo(int arg) { std::cout << "Foo::Foo(" << arg << ")" << std::endl; }
};

struct Base {
  Base(int arg) { std::cout << "Base::Base(" << arg << ")" << std::endl; }
};

struct Derived : public Base {
  using Base::Base;
  Foo foo{42};
};

int main() {
  Derived derived{120};
}

This code compiles and executes with the expected behaviour with clang. With gcc it does not compile, because the compiler deletes the constructor of Derived:

ttt.cpp: In function ‘int main()’:
ttt.cpp:17:22: error: use of deleted function ‘Derived::Derived(int)’
   Derived derived{120};
                      ^
ttt.cpp:12:15: note: ‘Derived::Derived(int)’ is implicitly deleted because the default definition would be ill-formed:
   using Base::Base;
               ^
ttt.cpp:12:15: error: no matching function for call to ‘Foo::Foo()’
ttt.cpp:4:3: note: candidate: Foo::Foo(int)
   Foo(int arg) { std::cout << "Foo::Foo(" << arg << ")" << std::endl; }
   ^
ttt.cpp:4:3: note:   candidate expects 1 argument, 0 provided
ttt.cpp:3:8: note: candidate: constexpr Foo::Foo(const Foo&)
 struct Foo {
        ^
ttt.cpp:3:8: note:   candidate expects 1 argument, 0 provided
ttt.cpp:3:8: note: candidate: constexpr Foo::Foo(Foo&&)
ttt.cpp:3:8: note:   candidate expects 1 argument, 0 provided

If I add a default constructor to Foo like this:

  Foo() { std::cout << "Foo::Foo()" << std::endl; };

also gcc can compile it. The code behaves exactly in the same way, in particular the added default constructor of Foo never gets executed.

So my question is now, is this valid C++ 11? If yes, I probably have found a bug in gcc. Otherwise, shouldn't both gcc and clang give me an error message that this is not valid C++ 11?

Aucun commentaire:

Enregistrer un commentaire