I have a Base class, two classes inheriting from that base class (they are slightly different from each other) and a Last class which can either inherit from Derived1
or Derived2
based on a template. I use std::conditional
to determine at compile time which DerivedX
it should actually use:
template< class >
class Base;
template< class T, class ...Args >
class Base < T(Args...) >
{
public:
Base(int a) { std::cout << "Base constructor " << a << std::endl; }
};
template< class >
class Derived1;
template< class ...Args >
class Derived1 < void(Args...) > : public Base< void(Args...) >
{
public:
Derived1(int a) : Base< void(Args...) >(a)
{ std::cout << "Derived1 constructor " << a << std::endl; }
};
template< class >
class Derived2;
template< class T, class ...Args >
class Derived2 < T(Args...) > : public Base< T(Args...) >
{
public:
Derived2(int a) : Base< T(Args...) >(a)
{ std::cout << "Derived2 constructor " << a << std::endl; }
};
template< class >
class Last;
template< class T, class ...Args >
class Last< T(Args...) > : public std::conditional<
std::is_void<T>::value,
Derived1< void(Args...) >,
Derived2< T(Args...) > >
{
public:
Last(int a) : std::conditional<
std::is_void<T>::value,
Derived1< void(Args...) >,
Derived2< T(Args...) > >::type(a)
{ std::cout << "Last constructor " << a << std::endl; }
};
int main()
{
Last<int(int)> last(1);
return 0;
}
I have read multiple topics about diamond heritage and virtual inheritance and I get the same error as those topics: type Derived2<...> is not a base class of Last<...>
. However these topics never use an std::conditional
. Btw it compiled fine until I try to instantiate a Last
object. Is there something I'm missing ? Is it even possible to do it like that ?
CodePudding user response:
In your declaration of the base class:
template< class T, class ...Args >
class Last< T(Args...) > : public std::conditional<
std::is_void<T>::value,
Derived1< void(Args...) >,
Derived2< T(Args...) > >
{
...
}
You either need to say public std::conditional_t
(where the _t
is very important at the end), or else you need to put ::type
after the std::conditional
template parameters, as in the following:
template< class T, class ...Args >
class Last< T(Args...) > : public std::conditional<
std::is_void<T>::value,
Derived1< void(Args...) >,
Derived2< T(Args...) > >::type
{
...
}
Otherwise, your base type is std::conditional
and you are trying to mem-initialize Derived2
, which is not the same type.