Call non default constructor of variadic inheritance

123 Views Asked by At

I have an abstract base class, and a class which implement it in a very basic way:

class base {
public:
    virtual ~base() = default;
    virtual void func() = 0;
}

class base_core : public base {
public:
    base_core(int);
    void func() override {}
}

template <typename T>
concept IsBaseCore = std::is_base_of_v<base_core, T>;

Now, I crated a variadic inheritance and noticed a strange behavior, which I believe is wrong:

class temp_inheritance {};

template <typename Base, typename ...Decorators>
struct base_if_not_exists {
    static constexpr bool value = sizeof...(Decorators);
    using type = typename std::conditional_t<value, temp_inheritance, Base>;
};

template <typename T, IsBaseCore ...Cores>
class base_impl : virtual public base_if_not_exists<base_core, Cores...>::type, virtual public Cores... {
public:
    base_impl() : Cores(5)... {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        std::cout << "base_impl: Default CTOR" << std::endl;
    }

    base_impl(int num) : Cores(num)... {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        std::cout << "base_impl: Non default CTOR" << std::endl;
    }

    void func() override { std::cout << "base_impl::func(): " << param << std::endl; }

private:
    T param;
};

template <IsBaseCore ...Cores>
using impl_1 = base_impl<int, Cores...>;

template <IsBaseCore ...Cores>
using impl_2 = base_impl<double, Cores...>;

template <IsBaseCore ...Cores>
using impl_3 = base_impl<size_t, impl_1<impl_2<>>>;

int main() {
    impl_3<> impl(5);
    return EXIT_SUCCESS;
}

For some reason this output the following result:

base_core: Default CTOR
base_impl<T, Cores>::base_impl() [with T = double; Cores = {}]
base_impl: Default CTOR
base_impl<T, Cores>::base_impl(int) [with T = int; Cores = {base_impl<double>}]
base_impl: Non default CTOR
base_impl<T, Cores>::base_impl(int) [with T = long unsigned int; Cores = {base_impl<int, base_impl<double> >}]
base_impl: Non default CTOR

I have two points which are unclear to me in this output:

  1. Why there is a call for base_core default constructor?
  2. Why does the parametrize constructor of impl_2 is never called?

I am using Ubuntu 16.04 (tested on 20.04 too), GCC 10.2.

0

There are 0 best solutions below