I have written a small utility for testing whether or not a type has inherited some template instantiation of a specific template class, either directly or trough inheriting a class that inherits the template. This is accomplished with a SFINAE check using a template function accepting any template instantiation of the provided template and a fallback overload for the default case.
#include <iostream>
#include <type_traits>
template<template<class> class T, class U>
struct isDerivedFrom
{
static constexpr bool value = decltype(isDerivedFrom::test(U()))::value;
private:
template<class V>
static std::true_type test(T<V>);
static std::false_type test(...);
};
template<class T>
struct Base {};
struct Base_D1 : Base<int> {};
struct Base_D2 : Base<Base_D2> {};
struct Base_D1_D1 : Base_D1 {};
struct NotDerived {};
int main()
{
std::cout << std::boolalpha
<< "is Base_D1 derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, Base_D1>::value << "\n"
<< "is Base_D2 derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, Base_D2>::value << "\n"
<< "is Base_D1_D1 derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, Base_D1_D1>::value << "\n"
<< "is Base<double> derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, Base<double>>::value << "\n"
<< "is NotDerived derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, NotDerived>::value << "\n";
return 0;
}
Output:
is Base_D1 derived from or a template instantiation of Base: true
is Base_D2 derived from or a template instantiation of Base: true
is Base_D1_D1 derived from or a template instantiation of Base: true
is Base<double> derived from or a template instantiation of Base: true
is NotDerived derived from or a template instantiation of Base: false
My problem is that if the type to be tested (template argument T of isDerivedFrom
) has or inherits a non-public constructor or inherits the template trough non-public inheritance, it causes a compile error because decltype(T())
fails if T::T()
is not public:
struct Base {protected: Base(){}};
struct Derived : private Base<int> {};
Is there any way to make this work for all cases? Are there any unmentioned issues with the code?
It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation.
To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>(float original); Template arguments may be omitted when the compiler can infer them.
You may use: https://ideone.com/wR2dLX
template<template<class> class T, class U>
struct isDerivedFrom
{
private:
template<class V>
static decltype(static_cast<const T<V>&>(std::declval<U>()), std::true_type{})
test(const T<V>&);
static std::false_type test(...);
public:
static constexpr bool value = decltype(isDerivedFrom::test(std::declval<U>()))::value;
};
As private inheritance is not visible, the trait returns false
in the last case (for struct Derived : private Base<int> {};
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With