C++如何实现从任意容器推导其Wrapper包装后的对应容器类型
实现方案
可以通过模板特化 + C++17 auto非类型模板参数实现,完全满足所有要求,代码如下:
#include <type_traits> #include <vector> #include <map> #include <array> // 示例Wrapper模板 template<typename T> struct Wrapper {}; // 主模板声明 template<template<typename> typename WrapT, typename ContainerT> struct container_wrap; // 特化1:匹配模板参数全为类型的容器(vector、map等) template<template<typename...> typename ContainerTpl, template<typename> typename WrapT, typename... Ts> struct container_wrap<WrapT, ContainerTpl<Ts...>> { using type = ContainerTpl<WrapT<Ts>...>; }; // 特化2:匹配包含非类型模板参数的容器(std::array等) template<template<typename, auto...> typename ContainerTpl, template<typename> typename WrapT, typename T, auto... NTParams> struct container_wrap<WrapT, ContainerTpl<T, NTParams...>> { using type = ContainerTpl<WrapT<T>, NTParams...>; }; // 对外接口,符合要求的调用语法 template<template<typename> typename WrapT, typename ContainerT> using alias = typename container_wrap<WrapT, ContainerT>::type;
验证测试
通过静态断言验证匹配需求:
static_assert(std::is_same_v<alias<Wrapper, std::vector<int>>, std::vector<Wrapper<int>>>); static_assert(std::is_same_v<alias<Wrapper, std::map<int, std::string>>, std::map<Wrapper<int>, Wrapper<std::string>>>); static_assert(std::is_same_v<alias<Wrapper, std::array<int, 10>>, std::array<Wrapper<int>, 10>>);
实现说明
- 解决调用语法问题:通过模板特化自动拆解传入的完整容器类型(如
std::vector<int>),无需单独传入容器模板和元素参数,直接支持alias<Wrapper, 容器类型>的调用形式。 - 解决std::array兼容问题:新增带非类型参数的特化分支,用
auto... NTParams匹配并保留所有非类型模板参数,无需单独为std::array做分支区分。 - 边界情况说明:对于带额外模板参数的标准容器(如std::map的比较器、分配器),上述实现会直接对所有类型参数做Wrapper转换。如果需要保留原容器的比较器、分配器逻辑,仅替换键值类型,可以针对标准容器单独补充特化分支。
- 版本要求:该实现依赖C17引入的auto非类型模板参数特性,需要C17及以上编译版本。
内容的提问来源于stack exchange,提问作者Ranoiaetep
相关产品推荐
相关产品推荐

