考虑一下:
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语法?
答案 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;
我不确定这肯定比你的解决方案更好,但也许在多个地方需要这个。