Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How useful would Inheriting Constructors be in C++?

As I sit in the C++ Standards committee meetings, they are discussing the pros and cons of dropping Inheriting Constructors since no compiler vendor has implemented it yet (the sense being users haven't been asking for it).

Let me quickly remind everyone what inheriting constructors are:

struct B {    B(int); };  struct D : B {   using B::B; }; 

Some vendors are proposing that with r-value references and variadic templates (perfect forwarding constructors), it would be trivial to provide a forwarding constructor in the inheriting class that would obviate inheriting constructors.

For e.g.:

struct D : B {   template<class ... Args>      D(Args&& ... args) : B(args...) { }  }; 

I have two questions:

1) Can you provide real world (non-contrived) examples from your programming experience that would benefit significantly from inheriting constructors?

2) Are there any technical reasons you can think of that would preclude "perfect forwarding constructors" from being an adequate alternative?

Thanks!

like image 688
Faisal Vali Avatar asked Nov 08 '10 23:11

Faisal Vali


People also ask

How are constructors used in inheritance?

When classes are inherited, the constructors are called in the same order as the classes are inherited. If we have a base class and one derived class that inherits this base class, then the base class constructor (whether default or parameterized) will be called first followed by the derived class constructor.

Do inherited classes need constructors?

To inherit only selected ones you need to write the individual constructors manually and call the base constructor as needed from them. Historically constructors could not be inherited in the C++03 standard.

Is the constructor will be called in inheritance function?

Constructor is automatically called when the object is created. Multiple Inheritance: Multiple Inheritance is a feature of C++ where a class can derive from several(two or more) base classes. The constructors of inherited classes are called in the same order in which they are inherited.

Why constructors are not inherited?

In simple words, a constructor cannot be inherited, since in subclasses it has a different name (the name of the subclass). Methods, instead, are inherited with "the same name" and can be used.


1 Answers

2) Are there any technical reasons you can think of that would preclude "perfect forwarding constructors" from being an adequate alternative?

I have shown one problem with that perfect forwarding approach here: Forwarding all constructors in C++0x .

Also, the perfect forwarding approach can't "forward" the expliciteness of base-class constructors: Either it is always a converting constructor or never, and the base-class will always be direct initialized (always making use of all constructors, even explicit ones).

Another problem are initializer-list constructors because you can't deduce Args to initializer_list<U>. Instead, you would need to forward to the base with B{args...} (note the braces) and initialize D objects with (a, b, c) or {1, 2, 3} or = {1, 2, 3}. In that case, Args would be the element types of the initializer list, and forward them to the base class. A initializer-list constructor can then receive them. This seems to cause unnecessary code bloat because the template argument pack will potentially contain lots of type sequences for each different combination of types and length and because you have to choose an initialization syntax this means:

struct MyList {   // initializes by initializer list   MyList(std::initializer_list<Data> list);    // initializes with size copies of def   MyList(std::size_t size, Data def = Data()); };  MyList m{3, 1}; // data: [3, 1] MyList m(3, 1); // data: [1, 1, 1]  // either you use { args ... } and support initializer lists or // you use (args...) and won't struct MyDerivedList : MyList {   template<class ... Args>    MyDerivedList(Args&& ... args) : MyList{ args... } { }  };  MyDerivedList m{3, 1}; // data: [3, 1] MyDerivedList m(3, 1); // data: [3, 1] (!!) 
like image 154
Johannes Schaub - litb Avatar answered Sep 20 '22 08:09

Johannes Schaub - litb