且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

检查类是否从模板的任何模板实例化继承

更新时间:2023-11-01 21:51:16

您可以使用: https://ideone.com/wR2dLX

 模板< template< class>类T,类U> 
struct isDerivedFrom
{
private:
template< class V>
static decltype(static_cast< const T>&>(std :: declval< U>()),std :: true_type {})test(const T&
static std :: false_type test(...);
public:
static constexpr bool value = decltype(isDerivedFrom :: test(std :: declval< U>()))
};

由于私有继承不可见,trait返回 false 在最后一种情况下( struct Derived:private Base< int> {}; )。


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?

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> {};).