模板别名可以作为模板的模板参数吗?
Can I use template aliases as template template parameters?
可以使用模板别名作为模板模板参数吗?
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?
是的,这显然是允许的。根据我所能找到的即将出台的标准的最新草案,
模板的模板参数应该是类模板的名称或别名模板[…]。
然而,别名模板目前似乎很少被支持,所以你可能会遇到一些麻烦,使它在大多数编译器中工作
阅读原始问题的人可能正在编写使用模板模板参数作为元函数的结构体,如下面的清单所示。
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-style元函数的一个例子(c++03支持) -
add_2
作为模板别名样式元函数的示例(需要c++11)
binary_op
结构体可以与模板别名样式或嵌套typedef-style元函数一起工作,但不能两者都使用。在这个答案中,我将展示如何重写这样的TMP代码来避免这个问题。
假设您希望将模板模板参数Function
应用于值为Ts...
的参数包。要应用元函数,您需要
using type = Function<Ts...>; // template-alias style
或
using type = typename Function<Ts...>::type; // nested typedef style
如果有另一个泛型元函数来检测传递的元函数的类型,并相应地应用它,那将是很有用的。下面实现的is_alias_metafunction
函数是这样一个设施的构建块:
#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...
,而不管Function
是模板别名还是模板结构体。
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...>;
,它将抽象掉'遗留'元函数和现代(c++11)元函数之间的区别。
相关文章:
- 部分定义/别名模板模板参数
- 告诉c++编译器该参数没有别名
- 为什么我们不能重复使用具有不同模板参数的别名模板标识符?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 模板模板参数和模板别名:编译器错误?
- 为模板参数包添加别名
- C++使用默认模板参数键入别名和转发声明
- 缺少别名模板C++参数列表
- 使用外部定义的模板类型作为模板参数的更通用模板的模板别名
- 必须非常量别名参数及其默认参数常量
- 作为模板参数 c++ 给出的类的别名模板
- 使用其他模板类型参数作为要在函数签名中使用的类型别名声明
- 参数化类的别名(或类型定义)内部类
- C++别名的模板参数包扩展
- 如何简化模板模板参数中的enable_if别名
- 包含可变参数包的第一个可转换类型的别名的结构
- C++ 11 个模板,参数包的别名
- 为什么模板引用类型不能用作模板类型别名参数?
- 具有模板类默认参数的 C++17 别名模板
- 如何用可变数量的参数别名一个函数