特性检查模板类的某些特化是否是特定类的基类 [英] Trait to check if some specialization of template class is base class of specific class

查看:160
本文介绍了特性检查模板类的某些特化是否是特定类的基类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



是否可以确定一个类是否来自某个具体的模板类,而无需区分哪个具体的实际参数涉及到它的专业化?



说, / p>

 模板< typename ... types> 
struct B {};

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

可以定义类型特征:

  template<类型名T> is_derived_from_B; 

使用 std :: true_type T D 的任何特殊化并派生自 std :: false_type 如果 T 不是源自 B


的任何专业化

解决方案

如果您可以假定派生类型使用 B (因此可以进行向上转换),那么您可以使用以下SFINAE:

 命名空间详细信息
{
template< typename Derived>
struct is_derived_from_B
{
使用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



它可以概括为接受任何基类模板:

 命名空间详情
{
template< template< typename ...> class Base,typename Derived>
struct is_derived_from_template
{
使用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,! rel =nofollow> DEMO 2


There is std::is_base_of in modern STL. It allow us to determine whether the second parameter is derived from first parameter or if they are the same classes both or, otherwise, to determine is there no such relation between them.

Is it possible to determine whether the one class is derived from some concrete template class without distinction of which concrete actual parameters involved to its specialization?

Say, we have;

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

And

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

Is it possible to define a type trait:

template< typename T > is_derived_from_B;

Such that it is derived from std::true_type when T is any specialization of D and derived from std::false_type if T is not derived from any specialization of B?

解决方案

If you can assume that a derived type uses a public inheritance from B<Args...> (and so the upcasting is possible), then you can use the following 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;

Tests:

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

It can be generalized to accept any base class template:

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;

Tests:

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

这篇关于特性检查模板类的某些特化是否是特定类的基类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆