c++ - 检查模板类的某些特化是否是特定类的基类的特征

标签 c++ c++11 traits c++14 typetraits

现代STL中有std::is_base_of。它允许我们确定第二个参数是否派生自第一个参数,或者它们是否是相同的类,否则,确定它们之间是否没有这种关系。

是否可以在不区分其特化涉及哪些具体实际参数的情况下确定一个类是否派生自某个具体模板类?

说,我们有;

template< typename ...types >
struct B {};

template< typename ...types >
struct D : B< types... > {};

是否可以定义类型特征:

template< typename T > is_derived_from_B;

TD 的任何特化并从 std::派生时,它从 std::true_type 派生: false_type 如果 T 不是从 B 的任何特化派生的?

最佳答案

如果您可以假设派生类型使用来自 B<Args...> 的公共(public)继承(因此向上转换是可能的),那么您可以使用以下 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;

测试:

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, "!");

DEMO 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;

测试:

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, "!");

DEMO 2

关于c++ - 检查模板类的某些特化是否是特定类的基类的特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25845536/

相关文章:

c++ - 设置 QtCreator 在 Ubuntu 14.04 上为 arm7 设备开发应用程序

c++ - vim初学问题

c++ - 你如何获得 shared_ptr 弱计数?

Scala:具有通用特征的无形泛型

multithreading - 我可以定义一个特征,其实现必须是 `!Send` 吗?

c++ - 虚函数和多重继承情况下的对象布局

c++ - 在 MainWindow 中看不到我的标签和布局

c# - 是否可以在C#中创建 “perfect forwarding”泛型集合?

C++ auto ,不明白如何分配运算符?

php - 如何在 PHP >= 5.4 中的特征中重载类构造函数