10

テンプレート引数として提供された型がパラメーターパックにリストされているすべての型を実装しているかどうか、静的アサーションを持つ可能性はありますか? パラメータ パック対応 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);
    }
};
4

2 に答える 2

18

C++17 の更新: C++17 の折り畳み式を使用すると、これはほとんど簡単になります。

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

元の回答 (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;
}

パック展開はRequirements...、 の疑問符のすべてのタイプを挿入することによって得られる値のリストに展開されますstd::is_base_of<Type, ?>::value。つまり、 main の最初の行は に展開さstatic_all_of<true, true>れ、2 行目はstatic_all_of<true, false, true>

于 2012-11-26T10:57:13.410 に答える
4

この問題が発生したばかりなので、今後の参考のために、C++ 17 では次のような折りたたみ式を使用できるようになりました。

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>());
于 2016-03-24T06:33:41.467 に答える