C++模板模板语法:简洁性与实用性探讨,为何不支持auto?
如何从普通模板实现中获取容器的元素类型(E类型)
问题背景
第一段代码用模板模板参数实现时,虽能从容器的value_type拿到元素类型E来定义garbage_value处理越界,但代码过于啰嗦(一行要写多个class关键字),实例化写法也零散。换成普通模板后,用auto简化了返回值定义,却找不到直接获取E类型的方法,且尝试用shelf<auto>实例化直接报错,想解决这个问题。
可行方案
1. 直接使用容器的嵌套value_type
只要传入的是符合标准的容器(比如std::vector、std::array这类自带value_type嵌套类型的容器),直接提取该类型即可,代码比模板模板参数简洁很多:
template <typename Container> auto& shelf_get(Container& c, size_t idx) { // 提取容器的元素类型E using E = typename Container::value_type; static E garbage_value{}; // 用E定义越界返回的垃圾值 if (idx >= c.size()) { return garbage_value; } return c[idx]; }
2. 用decltype推导元素类型
如果不确定容器是否自带value_type,或者想兼容一些非标准但支持下标/迭代器的容器,可通过decltype推导元素类型:
template <typename Container> auto& shelf_get(Container& c, size_t idx) { // 从容器迭代器推导元素类型,空容器场景下更稳妥 using E_raw = std::decay_t<decltype(*c.begin())>; static E_raw garbage_value{}; if (idx >= c.size()) { return garbage_value; } return c[idx]; }
这里std::decay_t用于去掉引用和const限定符,得到元素的原始类型。
3. C++20+:用Concept约束避免非法参数
担心传入非容器类型导致编译报错?C++20的Concept可以限定模板参数必须是带value_type的容器:
template <typename Container> concept ContainerType = requires { typename Container::value_type; }; template <ContainerType Container> auto& shelf_get(Container& c, size_t idx) { using E = typename Container::value_type; static E garbage_value{}; if (idx >= c.size()) { return garbage_value; } return c[idx]; }
关于shelf<auto>报错的问题
shelf<auto>写法本身不合法,auto不能直接作为类模板的参数使用。如果是类模板,直接传入容器类型即可:
std::vector<int> my_vec{1,2,3}; shelf<std::vector<int>> my_shelf(my_vec);
C++17及以上还能借助类模板实参推导省略模板参数:
std::vector<int> my_vec{1,2,3}; shelf my_shelf(my_vec); // 编译器自动推导出模板参数为std::vector<int>
内容的提问来源于stack exchange,提问作者Ammar Tamimi
相关产品推荐
相关产品推荐

