Search code examples
c++c++11inheriting-constructors

Inheriting constructors vs forwarding


C++11 allows inheriting constructors making it possible to avoid a lot of boilerplate, especially with something like a wrapper class. However, it seems like you could already achieve this functionality with variadic templates alone.

class B
{
public:
 B(int){//do something}
 B(int, char){//do something}
};

Using inheriting constructors:

class D : public B
{
public:
 using B::B; 
};

Using variadic templates and forward:

class D : public B
{
public:
 template <typename...Args>
 D(Args&&... args) : B(std::forward<Args>(args)...)
 {
 }
};

While consistency(treat constructors and methods the same way for using) and ease of use are very good reasons to bring inherited constructors into the language, is there any other reason why the first solution should be preferred to the second? Both the CWG documents(N1890 and N1898) I found discussing inheriting constructors simply note the following and move on:

Little more than a historical accident prevents using this to work for a constructor as well as for an ordinary member function. Had a constructor been called “ctor” or “constructor” rather than being referred to by the name of their class, this would have worked. We propose this as the mechanism for inheriting constructors.


Solution

  • The big reason is that perfect forwarding isn't perfect. Simple case:

    struct B {
        B(int* ) { .. }
    };
    

    Now consider:

    D d{0};
    

    If we inherit the constructor, this works fine. If we perfect-forward, we would try to construct B(int ), since 0 deduces as int, which is a constructor that doesn't exist. Failure!

    Other failure cases include braced initialization, declaration-only static const data members, overloaded functions, and bitfields.