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

时间:2014-03-23 14:49:24

标签: c++ templates inheritance c++11 sfinae

我编写了一个小实用程序,用于测试某个类型是否继承了特定模板类的某些模板实例,可以直接或通过继承继承该模板的类来实现。这是通过SFINAE检查完成的,使用模板函数接受所提供模板的任何模板实例化以及默认情况下的回退重载。

#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;
}

输出:

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

我的问题是,如果要测试的类型(isDerivedFrom的模板参数T)具有或继承非公共构造函数或通过非公共继承继承模板,则会导致编译错误,因为{{如果decltype(T())不公开,则会失败:

T::T()

有没有办法让这项工作适用于所有情况?代码中是否有任何未提及的问题?

1 个答案:

答案 0 :(得分:11)

您可以使用: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;
};

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