1

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.

Coral Kashri
  • 3,436
  • 2
  • 10
  • 22
  • 2
    `base_if_not_exists::type` is not explicitly initialized, it would use default initialization. – Jarod42 Mar 09 '21 at 12:05
  • 2
    `virtual` bases are only initialized in the most derived type, and `impl_3` doesn't initialize `impl_2<>`. – Jarod42 Mar 09 '21 at 12:08
  • 2
    You might have reduced the issue without template BTW. – Jarod42 Mar 09 '21 at 12:10
  • @Jarod42 Thanks a lot, the removing of virtual from the Components inheritance solved the problem. I would like to have a full answer that will explain why does the virtual initialize only the most derived type. – Coral Kashri Mar 09 '21 at 12:17
  • 1
    [Virtual_base_classes](https://en.cppreference.com/w/cpp/language/derived_class#Virtual_base_classes) – Jarod42 Mar 09 '21 at 12:30

0 Answers0