【问题标题】:Specifying a default template指定默认模板
【发布时间】:2017-10-10 22:16:35
【问题描述】:

考虑一下:

template <typename Pack, template <typename...> class = std::tuple> struct foo;

template <template <typename...> class P, typename... Ts, template <typename...> class Q>
struct foo<P<Ts...>, Q> {
    using type = Q<P<Ts>...>;   
};

我已将 typedef 中的默认模板放置为 std::tuple 以进行编译,但我真正想要的是默认模板为 P,我不知道任何允许这样做的语法.我保持 typedef 简单来说明这一点,它试图将P 作为默认模板。所以我想出了以下看起来有点难看的解决方法:

template <typename Pack, template <typename...> class...> struct foo;

template <template <typename...> class P, typename... Ts, template <typename...> class Q>
struct foo<P<Ts...>, Q> {
    using type = Q<P<Ts>...>;   
};

template <template <typename...> class P, typename... Ts>
struct foo<P<Ts...>> {
    using type = P<P<Ts>...>;   
};

还有比这更好的方法吗?也许是一些我不知道的 c++17 语法?

【问题讨论】:

  • 你想达到什么目的?一些给定的foo&lt;...&gt;::type 表达式的预期结果是什么?
  • @sehe 将包拆分为特定的小包(如上面的示例,但更复杂),但我需要包含所有小包,因此默认模板的作用。跨度>
  • 如何。具体来说。如果你说foo&lt;std::tuple, int, double, std::tuple&gt;::type,结果应该是什么?如果这不是正确的用法,那是什么?结果会是什么(假设你神奇地有一个有效的实现)

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


【解决方案1】:

在这种情况下,using(结合template)是你的朋友。

您需要一个类型特征来提取Pack 中的容器,例如

template <typename>
struct bar;

template <template <typename...> class P, typename ... Ts>
struct bar<P<Ts...>>
 {
   template <typename ... Us>
   using templ_type = P<Us...>;
 };

这样您就可以从Pack 中提取第二个模板参数的默认值,如下所示

template <typename Pack,
          template <typename...> class = bar<Pack>::template templ_type>
struct foo;

以下是完整的编译示例

#include <type_traits>

template <typename ...>
struct baz
 { };

template <typename>
struct bar;

template <template <typename...> class P, typename ... Ts>
struct bar<P<Ts...>>
 {
   template <typename ... Us>
   using templ_type = P<Us...>;
 };

template <typename Pack,
          template <typename...> class = bar<Pack>::template templ_type>
struct foo;

template <template <typename...> class P, typename... Ts,
          template <typename...> class Q>
struct foo<P<Ts...>, Q>
 { using type = Q<P<Ts>...>; };

int main()
 {
   foo<baz<short, int, long>>  f0;

   static_assert( std::is_same<decltype(f0)::type,
      baz<baz<short>, baz<int>, baz<long>>>{}, "!" );
 }

【讨论】:

    【解决方案2】:

    如果你正在寻找一个不同的默认身份,你可以创建这样的东西:

    template <class... I> struct foo_id_impl;
    template <template <class...> class P, class... Ts>
    struct foo_id_impl<P<Ts>...> { using type = P<P<Ts>...>; };
    
    template <class... Id>
    using foo_id = typename foo_id_impl<Id...>::type;
    
    template <class Pack, template <class...> class = foo_id>
    struct foo;
    

    我不确定这是否一定比您的解决方案更好,但如果在多个地方都需要这样做的话。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-28
      • 1970-01-01
      相关资源
      最近更新 更多