Parameter pack aware std::is_base_of()

我的梦境 提交于 2019-12-05 03:51:30

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>

Just for future reference, because I just had this problem, with C++17 you can now use fold expressions like this:

template<typename Base, typename... Args>
constexpr auto all_base_of()
{
    return (std::is_base_of<Base, Args>::value && ...);
}

static_assert(all_base_of<Base, A, B, C>());
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!