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 << "
"
<< "is Base_D2 derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, Base_D2>::value << "
"
<< "is Base_D1_D1 derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, Base_D1_D1>::value << "
"
<< "is Base<double> derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, Base<double>>::value << "
"
<< "is NotDerived derived from or a template instantiation of Base: "
<< isDerivedFrom<Base, NotDerived>::value << "
";
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?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…