我可以使用模板别名作为模板模板参数吗?
我可以使用模板别名作为模板模板参数吗?
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_1
和add_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的区别。