指定默认模板

时间:2017-10-10 22:16:36

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

考虑一下:

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语法?

2 个答案:

答案 0 :(得分:2)

在这种情况下,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>>>{}, "!" );
 }

答案 1 :(得分:1)

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

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;

我不确定这肯定比你的解决方案更好,但也许在多个地方需要这个。