特性检查模板类的某些特化是否是特定类的基类

Ori*_*ent 10 c++ traits type-traits c++11 c++14

std::is_base_of现代STL.它允许我们确定第二个参数是从第一个参数派生还是它们是相同的类,或者确定它们之间是否存在这样的关系.

是否有可能确定一个类是否来自某个具体的模板类,而不区分其专业化所涉及的具体实际参数?

说,我们有;

template< typename ...types >
struct B {};
Run Code Online (Sandbox Code Playgroud)

template< typename ...types >
struct D : B< types... > {};
Run Code Online (Sandbox Code Playgroud)

是否可以定义类型特征:

template< typename T > is_derived_from_B;
Run Code Online (Sandbox Code Playgroud)

这样的派生自std::true_type何时T的任何特化D和派生自std::false_typeif T不是从任何专业化派生而来的B

Pio*_*cki 11

如果您可以假设派生类型使用公共继承B<Args...>(因此可以进行向上转换),那么您可以使用以下SFINAE:

namespace detail
{
    template <typename Derived>
    struct is_derived_from_B
    {
        using U = typename std::remove_cv<
                                  typename std::remove_reference<Derived>::type
                                >::type;

        template <typename... Args>
        static auto test(B<Args...>*)
            -> typename std::integral_constant<bool
                                           , !std::is_same<U, B<Args...>>::value>;

        static std::false_type test(void*);

        using type = decltype(test(std::declval<U*>()));
    };
}

template <typename Derived>
using is_derived_from_B = typename detail::is_derived_from_B<Derived>::type;
Run Code Online (Sandbox Code Playgroud)

测试:

static_assert(is_derived_from_B<const D<int, char, float>>::value, "!");
static_assert(!is_derived_from_B<int>::value, "!");
static_assert(!is_derived_from_B<B<int,int>>::value, "!");
static_assert(!is_derived_from_B<std::vector<int>>::value, "!");
Run Code Online (Sandbox Code Playgroud)

演示1

它可以推广为接受任何基类模板:

namespace detail
{
    template <template <typename...> class Base, typename Derived>
    struct is_derived_from_template
    {
        using U = typename std::remove_cv<
                                  typename std::remove_reference<Derived>::type
                                >::type;

        template <typename... Args>
        static auto test(Base<Args...>*)
            -> typename std::integral_constant<bool
                                          , !std::is_same<U, Base<Args...>>::value>;

        static std::false_type test(void*);

        using type = decltype(test(std::declval<U*>()));
    };
}

template <template <typename...> class Base, typename Derived>
using is_derived_from_template
                = typename detail::is_derived_from_template<Base, Derived>::type;
Run Code Online (Sandbox Code Playgroud)

测试:

static_assert(is_derived_from_template<B, const D<int, int>>::value, "!");
static_assert(!is_derived_from_template<B, int>::value, "!");
static_assert(!is_derived_from_template<B, B<int, int>>::value, "!");
static_assert(!is_derived_from_template<B, std::vector<int>>::value, "!");
Run Code Online (Sandbox Code Playgroud)

演示2

  • [我自己的版本。](http://coliru.stacked-crooked.com/a/9feadc62e7594eb2)但我认为直接使用`decltype`在编译时性能方面更有效。 (2认同)