Parameter pack aware std::is_base_of()
c++, templates, type-traits, variadic-templates
Solution
Update for C++17: With C++17's fold expressions this becomes almost trivial:
template <typename Type, typename... Requirements>
class CommonBase
{
static_assert((std::is_base_of_v<Type, Requirements> && ...), "Invalid.");
};
Original Answer (C++11/14): You might use pack expansion and some static version of `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;
}
The pack expansion will expand to the list of values you get by inserting every type in `Requirements...` for the question mark in `std::is_base_of<Type, ?>::value`, i.e. for the first line in main it will expand to `static_all_of<true, true>`, for the second line it will be `static_all_of<true, false, true>`
Problem
Is there a possibility to have a static assertion whether a type provided as template argument implements all of the types listed in the parameter pack ie. a parameter pack aware 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); } }; ```