【问题标题】:Deduce parameter pack w/out passing it explicitly as a template parameter?推导参数包而不将其作为模板参数显式传递?
【发布时间】:2011-05-17 15:52:24
【问题描述】:

请原谅这里对 C++ 类型推导的任何无知,但我希望能够携带参数包的定义,以便稍后我可以测试内部类型。这可能吗?比如:

template <typename... Args> struct Entity {

    struct Inner {
        typedef Args... entity_args_t;
    };

    struct SomeOtherInner {
        typedef Args... entity_args_t;
    };
};

struct ThingA : Entity<int, string> {
};

struct ThingB : Entity<string, string> {
};

//Want to accept variations of Entity<...>::Inner,
//not Entity<...>::SomeOtherInner
template<typename I>
struct is_Entity_Inner {
    static const bool value
        = is_same<
            typename Entity<typename I::entity_args_t...>::Inner
            , I
        >::value
    ;
};

喂?不是吗?

【问题讨论】:

    标签: c++ templates parameters c++11 variadic-templates


    【解决方案1】:

    定义:

    template<typename ...> struct types;
    

    然后:

    template <typename... Args> struct Entity {
    
        struct Inner {
            typedef types<Args...> entity_args_t;
        };
    
        struct SomeOtherInner {
            typedef types<Args...> entity_args_t;
        };
    };
    

    然后您可以将entity_args_t 传递给具有types&lt;T...&gt; 部分特化的模板。如果您键入Entity,则可以改为为Entity&lt;T...&gt; 编写部分特化,这对您的情况可能更有意义

    template <typename... Args> struct Entity {
    
        struct Inner {
            // Equivalent: typedef Entity entity_args_t;
            typedef Entity<Args...> entity_args_t;
        };
    
        struct SomeOtherInner {
            typedef Entity<Args...> entity_args_t;
        };
    };
    

    因此,entity_args_t 的 typedef 等于 Entity&lt;Args...&gt;,您可以这样编写(未经测试,但应该可以):

    template<typename ProbablyInner, typename ProbablyEntity>
    struct is_inner_impl : std::false_type 
    { };
    
    template<typename ProbablyInner, typename ...Args>
    struct is_inner_impl<ProbablyInner, Entity<Args...>> 
      : std::is_same<
          typename Entity<Args...>::Inner
          ProbablyInner>
    { };
    
    template<typename ProbablyInner, typename = std::true_type>
    struct is_inner : std::false_type 
    { };
    
    template<typename ProbablyInner>
    struct is_inner<ProbablyInner, 
      std::integral_constant<bool, is_inner_impl<
        ProbablyInner, 
        typename ProbablyInner::entity_args_t>::value>>
      : std::true_type 
    { };
    

    【讨论】:

    • 所以,在is_Entity_Inner 元函数中,我会使用is_same&lt;typename I::entity_args_t::template Inner, I&gt;::value?
    • @pheedbaq 关键点是您访问::entity_args_t 的位置。如果你想要is_inner yield false 用于任意其他类型,你必须在 SFINAE 上下文中访问该类型,这样如果没有名为 ::entity_args_t 的成员,则不会出现硬编译时错误。
    • @litb 不完全确定我掌握了你的最后评论。这就是typename = void 作为is_inner 的第二个参数所完成的吗?如果存在::entity_args_t 成员,则编译器将其与特化匹配。如果不是,即使该成员不存在,它与typename = void 版本匹配?
    • @pheedbaq 我随后将我的代码更改为不使用enable_if。我认为它使代码膨胀。如果::entity_args_t存在,那么它可以考虑特化以及是否匹配参数(参数为&lt;whatever is passed, void&gt;)。 enable_if 在成功的情况下(如果存在成员)将始终产生 void。在不成功的情况下(即is_inner_impl&lt;&gt;::value 评估为false),不存在::type 成员,因此会发生SFINAE 错误。现在我的integral_constant&lt;&gt; 版本也发生了大致相似的事情。
    • 好的。我想我明白了。非常感谢!
    猜你喜欢
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    相关资源
    最近更新 更多