【问题标题】:Parameter pack aware std::is_base_of()参数包感知 std::is_base_of()
【发布时间】:2012-11-26 10:24:17
【问题描述】:

是否有可能静态断言作为模板参数提供的类型是否实现了参数包中列出的所有类型,即。参数包感知 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);
    }
};

【问题讨论】:

  • 我怀疑这是否可能。您的第一个 is_base_of&lt;Requirements...&gt;::value 也没有提到第二个参数。
  • static_assertion是编译时进程(here),编译时是否检查is_base_of的值?
  • @tAmirNaghizadeh 当然可以,因为is_base_of 本身就是一个模板,模板在编译时被实例化。

标签: c++ templates variadic-templates typetraits


【解决方案1】:

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&lt;Type, ?&gt;::value 中的问号,即对于main 中的第一行,它将扩展为static_all_of&lt;true, true&gt;,对于第二行它将是static_all_of&lt;true, false, true&gt;

【讨论】:

  • 我认为需要括号static_assert((std::is_base_of_v&lt;Type, Requirements&gt; &amp;&amp; ...), "Invalid.");
  • 我的意思是在“Updae for C++17”代码中,而不是在原始答案中
  • @Tarquiscani 我的错,现在修复它。 (并了解到 MSVC 无论如何都不会编译它)
  • 我遇到了同样的错误。幸运的是,它将在 MSVC 16.0 中修复
  • 在 C++17 中,使用 conjunction 代替折叠表达式可能会更好,以避免不必要的实例化。
【解决方案2】:

仅供参考,因为我刚遇到这个问题,现在使用 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>());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多