一句话概括:
在声明 template template parameter 时,允许使用使用关键字 typename。
首先,什么是 template template parameter ?举例如下,T是常用的 type template parameter, 但 OP_T就是 template template parameter:
// T is a type template parameter, and OP_T is template template parameter:
template typename OP_T, typename T> struct DO_OP{
OP_T opT;
constexpr T operator()(T a, T b) { return opT(a, b);}
};
即,OP_T本身是一个 template,同时作为 template DO_OP的 template parameter,那么这个 OP_T就是 DO_OP的 template template parameter。
从 cpp11 开始,即支持 template template parameter;只是在 C++17 之前,只能使用 class在声明 template template parameter 的地方。
为了语法的统一、简单,C++17 明确了在声明 template template parameter 的地方,也可以使用 typename.
多说一句,template template parameter 为 template 的定义和使用,提供了多一个"自由度"的灵活性。
举例:
templatestruct ADD_OP { static constexpr T op(T a, T b){ return a + b; }; }; template struct MULTIPLY_OP { static constexpr T op(T a, T b){ return a * b; }; }; // T is a type template parameter, and OP_T is template template parameter: template typename OP_T, typename T> struct DO_OP{ static constexpr OP_T opT; static constexpr T do_op(T a, T b) { return opT.op(a, b);} };
在实例化 DO_OP的时候,我们就可以根据实际需要传入 T和 OP_T,多一个组合的自由度:
constexpr auto addInt = DO_OP(); static_assert(addInt.do_op(100, 200) == (100 + 200)); constexpr auto multiplyDouble = DO_OP (); static_assert(multiplyDouble.do_op(M_PI, M_E) == (M_PI * M_E));
完整 demo 代码参见 gitee.com 上的公开代码仓库 : [typename_in_a_template_template_parameter]



