C++模板匹配容器与内容:适配单层及多层嵌套容器的实现
解决方案
一、基础版:支持Test<std::vector<int>>用法
要实现直接传入实例化后的容器类型,我们可以通过模板偏特化拆解容器的类型参数,步骤如下:
- 先声明空的主模板,留待特化实现:
template <typename T> class Test;
- 编写针对单参数容器实例的偏特化版本:
template <template <typename> typename Container, typename Content> class Test<Container<Content>> final { public: Container<Content> m; // 定义类型别名,方便外部直接访问容器和内容类型 using container_type = Container<Content>; using value_type = Content; };
此时即可直接使用Test<std::vector<int>> test;,编译器会自动匹配偏特化模板,拆解出Container为std::vector、Content为int。
如果需要兼容原有的Test<std::vector, int>用法,只需添加另一套偏特化:
// 保留原有用法的偏特化版本 template <template <typename> typename Container, typename Content> class Test<Container, Content> final { public: Container<Content> m; using container_type = Container<Content>; using value_type = Content; };
二、进阶版:处理多层嵌套的容器/视图类型
对于std::ranges::filter_view<std::ranges::ref_view<std::vector<int>>>这类多层嵌套的视图,我们需要递归类型萃取穿透外层封装,提取最底层的内容类型和原始容器。
1. 实现递归类型萃取器
定义一个工具模板,递归适配不同类型的视图与容器:
#include <type_traits> #include <ranges> // 基础情况:直接获取类型的value_type template <typename T> struct value_type_trait { using type = typename T::value_type; using container_type = T; }; // 递归处理带有inner_range_type的视图(如filter_view、transform_view) template <typename T> requires requires { typename T::inner_range_type; } struct value_type_trait<T> { using inner_trait = value_type_trait<typename T::inner_range_type>; using type = typename inner_trait::type; using container_type = typename inner_trait::container_type; }; // 单独处理ref_view:直接指向底层容器 template <typename T> struct value_type_trait<std::ranges::ref_view<T>> { using type = typename T::value_type; using container_type = T; }; // 处理带有base_type的视图(部分range适配器) template <typename T> requires requires { typename T::base_type; } struct value_type_trait<T> { using inner_trait = value_type_trait<typename T::base_type>; using type = typename inner_trait::type; using container_type = typename inner_trait::container_type; }; // 定义别名简化使用 template <typename T> using value_type_t = typename value_type_trait<T>::type; template <typename T> using underlying_container_t = typename value_type_trait<T>::container_type;
2. 修改Test类适配嵌套类型
调整Test类的主模板与偏特化,利用萃取器处理任意嵌套类型:
// 主模板声明 template <typename T, typename = void> class Test; // 特化1:兼容原有Test<Container, Content>用法 template <template <typename> typename Container, typename Content> class Test<Container, Content> final { public: Container<Content> m; using container_type = Container<Content>; using value_type = Content; }; // 特化2:支持传入任意容器/视图类型(含多层嵌套) template <typename ContainerInstance> class Test<ContainerInstance, std::void_t<value_type_t<ContainerInstance>>> final { public: ContainerInstance m; using container_type = ContainerInstance; // 外层完整视图/容器类型 using value_type = value_type_t<ContainerInstance>; // 最底层内容类型 using underlying_container_type = underlying_container_t<ContainerInstance>; // 最底层原始容器类型 };
用法示例
#include <vector> #include <ranges> int main() { // 原有用法依然有效 Test<std::vector, int> test1; // 新用法:直接传入实例化容器 Test<std::vector<int>> test2; // 嵌套视图用法 std::vector<int> vec = {1,2,3,4}; auto filtered = vec | std::views::filter([](int x){return x%2==0;}); Test<decltype(filtered)> test3; // 此时test3.value_type为int,test3.underlying_container_type为std::vector<int> return 0; }
内容的提问来源于stack exchange,提问作者yonutix
相关产品推荐
相关产品推荐

