is_base_of 泛型

is_base_of of generic type

我试图断言模板参数将派生自某些基础 class。但是 base class 是通用的,在断言的上下文中,任何专业化类型之间都没有区别。 我如何断言模板参数派生自任何专用类型的泛型?

我试着把它写成

base_generic:

template<typename T> struct base_generic{};

derived_generic:

template<typename T> struct derived_generic : public base_generic<T>{};

class 断言:

template<typename Tsource, typename Tderived_generic> 
struct encoder {
static_assert(std::is_base_of<base_generic<typename>, Tderived_generic>::value);
};

此代码编译通过,但断言失败

你可以使用 static_assert。

参见:http://en.cppreference.com/w/cpp/language/static_assert

例如,如果你有一个基地 class

template< typename T >
class Base<T> {};

和派生的

template< typename T >
class Derived : public Base<T> {};

你的用例

template< typename Tsource, typename Tstorage > 
class Test
{
    std::static_assert( std::is_base_of< base<T>, TStorage >::value );
}

如果不将其添加为模板参数,则无法获取 T。

但只需一个简单的技巧,您就可以做到。您必须将 typedef 添加到 Derived:

template< typename T >
class Derived : public Base<T> 
{
public:
    typedef T value_type;
};

并且您可以在静态断言中使用它。

template< typename Tsource, typename Tstorage > 
class Test
{
    std::static_assert( std::is_base_of< base<TStorage::value_type>, TStorage >::value );
}

由于 Tstorage 是派生的,因此它具有 value_type 字段。

您可以为此创建一个特征,例如:

namespace detail
{
    template <template <typename > class C>
    struct is_base_of_any_helper
    {
        template <typename T>
        std::true_type operator ()(const C<T>*) const;

        std::false_type operator() (...) const;

    };

}

template <template <typename > class C , typename T>
using is_base_of_any =
    decltype(detail::is_base_of_any_helper<C>{}(std::declval<const T*>()));

Demo

请注意,它会在某些极端情况下失败,例如:

  • 多个碱基C<Tx>
  • C<T> 的私有继承。

来自@PiotrSkotnicki 的评论

template <template <typename...> class Base, typename Derived>
struct is_base_of_template
{
    using U = typename std::remove_cv<Derived>::type;

    template <typename... Args>
    static std::true_type test(Base<Args...>*);

    static std::false_type test(void*);

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

template <template <typename...> class Base, typename Derived>
using is_base_of_template_t = typename is_base_of_template<Base, Derived>::type;

这个解决方案工作正常,example