参数包识别std :: is_base_of()

T. *_*ter 9 c++ templates type-traits variadic-templates

是否有可能有一个静态断言是否作为模板参数提供的类型实现参数包中列出的所有类型,即.一个参数包知道std :: is_base_of()?

template <typename Type, typename... Requirements>
class CommonBase
{
    static_assert(is_base_of<Requirements..., Type>::value, "Invalid.");
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            parameter pack aware version of std::is_base_of()
public:
    template <typename T> T* as()
    {
        static_assert(std::is_base_of<Requirements..., T>::value, "Invalid.");
        return reinterpret_cast<T*>(this);
    }
};
Run Code Online (Sandbox Code Playgroud)

Arn*_*rtz 17

更新C++ 17: 使用C++ 17的折叠表达式,这几乎变得微不足道:

template <typename Type, typename... Requirements>
class CommonBase
{
    static_assert((std::is_base_of_v<Type, Requirements> && ...), "Invalid.");
};
Run Code Online (Sandbox Code Playgroud)

原始答案(C++ 11/14 ):您可能使用包扩展和一些静态版本std::all_of:

template <bool... b> struct static_all_of;

//implementation: recurse, if the first argument is true
template <bool... tail> 
struct static_all_of<true, tail...> : static_all_of<tail...> {};

//end recursion if first argument is false - 
template <bool... tail> 
struct static_all_of<false, tail...> : std::false_type {};

// - or if no more arguments
template <> struct static_all_of<> : std::true_type {};

template <typename Type, typename... Requirements>
class CommonBase
{
    static_assert(static_all_of<std::is_base_of<Type, Requirements>::value...>::value, "Invalid.");
    //                                               pack expansion:      ^^^
};

struct Base {};
struct Derived1 : Base {};
struct Derived2 : Base {};
struct NotDerived {};

int main()
{
  CommonBase <Base, Derived1, Derived2> ok;
  CommonBase <Base, Derived1, NotDerived, Derived2> error;
}
Run Code Online (Sandbox Code Playgroud)

通过插入Requirements...问号的每个类型,包扩展将扩展到您获得的值列表std::is_base_of<Type, ?>::value,即对于第一行,它将扩展为static_all_of<true, true>,对于第二行,它将是static_all_of<true, false, true>