我可以使用模板别名作为模板模板参数吗?

我可以使用模板别名作为模板模板参数吗?

template <template <typename...> class> struct foo {}; template <typename T> using simple_ptr = std::unique_ptr<T>; foo<std::unique_ptr> a; // this doesn't work, std::unique_ptr has two parameters foo<simple_ptr> b; // does this work? 

是的,这显然是允许的。 根据即将出台的标准的最新草案,我可以发现,这是说

模板模板参数的模板参数应该是类模板或别名模板的名称。

然而,别名模板似乎目前很less得到支持 ,所以你可能会遇到一些麻烦,使它与大多数编译器一起工作。

阅读原始问题的人可能会编写使用模板模板参数作为元函数的结构 ,如下面的清单所示。

 template <int T> struct integer { using value = T; }; template <class T, class U, template <class...> class Function> struct binary_op { // Works for add_1, but not add_2 using type = typename Function<T, U>::type; // Works for add_2, but not add_1 using type = Function<T, U>; }; template <class T, class U> struct add_1; template <int T, int U> struct add_1<integer<T>, integer<U>> { using type = integer<T + U>; }; template <class T, class U> using add_2 = typename add_1<T, U>::type; 

add_1add_2都是元函数 ,让我们来区分

  • add_1作为嵌套的typedef样式元函数的一个例子(支持c ++ 03)
  • add_2作为模板别名式元函数的一个例子(它需要c ++ 11)

binary_op结构可以使用模板别名风格嵌套的typedef风格元function,但不能同时使用。 在这个答案中,我展示了如何可以重写这样的TMP代码以避免这个问题。

假设您希望将模板模板参数Function应用于值为Ts...的参数包。 要应用这个元函数,你也需要

 using type = Function<Ts...>; // template-alias style 

要么

 using type = typename Function<Ts...>::type; // nested typedef style 

有一个通用的元函数检测传递的元函数的种类,并相应地应用它将是有用的。

下面实现的is_alias_metafunction函数是这样一个工具的构build块:

 #include <type_traits> template <class... Ts> struct sequence; template <class T> struct check { static constexpr bool value = true; }; template < template <class...> class Function, class S, class Check = void > struct is_alias_metafunction { static constexpr bool value = true; }; template < template <class...> class Function, class... Ts > struct is_alias_metafunction< Function, sequence<Ts...>, typename std::enable_if< check<typename Function<Ts...>::type>::value >::type > { static constexpr bool value = false; }; 

现在,我们可以编写一个元函数apply ,将模板模板参数Function应用于参数包Ts... ,而不pipeFunction是模板别名还是模板结构。

 template < bool IsAlias, template <class...> class Function, class S > struct apply_impl; template <template <class...> class Function, class... Ts> struct apply_impl<true, Function, sequence<Ts...>> { using type = Function<Ts...>; }; template <template <class...> class Function, class... Ts> struct apply_impl<false, Function, sequence<Ts...>> { using type = typename Function<Ts...>::type; }; template <template <class...> class Function, class... Ts> using apply = typename apply_impl< is_alias_metafunction<Function, sequence<Ts...>>::value, Function, sequence<Ts...> >::type; 

我们现在可以使用apply元函数,如下所示:

 using type = apply<Function, Ts...>; 

它将抽象出“传统”元function与现代(c ++ 11)元function的区别。