template template parameter是让模板接收另一模板作为参数的机制,语法为template<template<typename...> class Tmpl>,要求严格匹配参数类型与数量,不支持非类型参数模板如std::array,常用于容器适配器和元编程。

什么是 template template parameter?
它就是让一个模板能接收「另一个模板」作为参数,而不是某个具体类型或值。比如你想写一个容器适配器,要支持 std::vector、std::list、std::deque 这些不同模板,但又不想为每个都写一遍特化——这时候就得用 template template parameter。
语法怎么写?容易漏掉什么?
基本形式是 template<template<typename...> class Tmpl>,注意三点:
-
class Tmpl不能写成typename Tmpl(C++ 标准强制要求用class) - 内层模板参数必须用
typename...或明确列出(如typename T, typename Alloc),不能只写<> - 如果目标模板有非类型参数(比如
std::array<int, 5>的5),它无法被这种形式匹配——std::array不符合template<typename...> class签名
template<template<typename...> class Container>
struct container_wrapper {
template<typename T>
using type = Container<T>;
};
为什么 std::vector<T, Alloc> 有时传不进去?
因为 std::vector 实际定义是 template<typename T, typename Alloc = std::allocator<T>>,带默认参数。而 template template parameter 要求参数个数「严格匹配」声明的形参列表——你写了 template<typename...>,它就只认变参;若写成 template<typename T, typename A>,则无法接受带默认 Alloc 的调用。
常见解法是统一用变参形式,并在内部转发:
立即学习“C++免费学习笔记(深入)”;
template<template<typename...> class Container>
struct wrapper {
template<typename T>
using rebind = Container<T>; // 安全:依赖 Container 自己的默认参数
};
这样传 std::vector、std::list 都行;但传 std::array 会失败,因为它第二个参数是 size_t,不是类型。
实际用在哪?有没有更现代的替代?
典型场景包括:容器元函数(如提取 value_type)、策略类组合、类型擦除包装器。C++17 后部分需求可用 constexpr if + 变参模板推导绕过,但 template template parameter 仍是唯一能「静态约束模板身份」的方式。
容易忽略的一点:它不参与 SFINAE 推导失败的静默处理——如果传入的模板签名不匹配,错误发生在实例化阶段,报错位置可能很深,且提示常含糊(比如 “expected a template-name before ‘<’”)。建议配合 static_assert 检查 is_template_v<T> 类型特征(需自定义)来提前拦截。










