阅读原始问题的人可能正在编写使用模板模板参数作为元函数的结构,如下面的清单所示。
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 样式元函数一起使用,但不能同时使用两者。在这个答案中,我展示了如何重写这样的 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)元函数之间的区别。