Inheritance and explicit constructors?

2.5k views Asked by At

Consider the following code :

template<typename T> class Base
{
    Base();
    Base(const Base<T>& rhs);
    template<typename T0> explicit Base(const Base<T0>&  rhs);
    template<typename T0, class = typename std::enable_if<std::is_fundamental<T0>::value>::type> Base(const T0& rhs);
    explicit Base(const std::string& rhs);
};

template<typename T> class Derived : Base<T>
{
    Derived();
    Derived(const Derived<T>& rhs);
    template<class T0> Derived(const T0& rhs) : Base(rhs); 
    // Is there a way to "inherit" the explicit property ?
    // Derived(double) will call an implicit constructor of Base
    // Derived(std::string) will call an explicit constructor of Base
};

Is there a way to redesign this code in a such way that Derived will have all the constructors of Base with the same explicit/implicit properties ?

2

There are 2 answers

0
Nicol Bolas On BEST ANSWER

C++11 offers this as a feature. Yet not even GCC actually implements it yet.

When it is actually implemented, it would look like this:

template<typename T> class Derived : Base<T>
{
    using Base<T>::Base;
};

That being said, it may not help for your case. Inherited constructors are an all-or-nothing proposition. You get all of the base class constructors, using exactly their parameters. Plus, if you define a constructor with the same signature as an inherited one, you get a compile error.

1
ecatmur On

To detect implicit/explicit constructibility for SFINAE:

template<class T0, typename std::enable_if<
    std::is_convertible<const T0 &, Base<T>>::value, int>::type = 0>
    Derived(const T0& rhs) : Base<T>(rhs) { }
template<class T0, typename std::enable_if<
    std::is_constructible<Base<T>, const T0 &>::value
    && !std::is_convertible<const T0 &, Base<T>>::value, int>::type = 0>
    explicit Derived(const T0& rhs) : Base<T>(rhs) { }

Use the fact that std::is_convertible checks implicit convertibility and use std::is_constructible to check explicit convertibility in addition.

Edit: fixed enable_if template parameters using solution from boost::enable_if not in function signature.

Checks:

Derived<int>{5};                            // allowed
[](Derived<int>){}(5);                      // allowed
Derived<int>{std::string{"hello"}};         // allowed
[](Derived<int>){}(std::string{"hello"});   // not allowed