现代STL中有std :: is_base_of.它允许我们确定第二个参数是从第一个参数派生的,或者它们是否是相同的类,或者否则确定它们之间是否没有这样的关系.
是否可以确定一个类是从一些具体的模板类派生的,而不区分其专业化涉及的具体实际参数?
说,我们有
template< typename ...types > struct B {};
和
template< typename ...types > struct D : B< types... > {};
是否可以定义类型特征:
template< typename T > is_derived_from_B;
当T是D的任何特殊化并且从std :: false_type派生时,如果T不是从B的任何专业化导出的,那么它来自std :: true_type?
解决方法
如果您可以假设派生类型使用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;
测试:
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,"!");
可以将其概括为接受任何基类模板:
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,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,"!"); static_assert(!is_derived_from_template<B,int>::value,B<int,std::vector<int>>::value,"!");