如何在未知std::array长度场景下使用type_traits的is_same做类型校验
核心问题原因
std::array的长度是模板参数,属于类型的固有属性。你代码里的函数形参container是运行期变量,即使std::array::size()本身是constexpr方法,通过非constexpr的形参调用也无法得到可用于模板参数的常量表达式,因此编译器会报错。
解决方案:自定义类型萃取匹配任意长度的std::array
你不需要显式拿到array的长度,只需要通过偏特化的类型萃取,判断目标类型是不是元素为char/uint8_t的std::array特化即可:
#include <type_traits> #include <vector> #include <array> #include <string> // 类型萃取:判断T是否为元素类型为Elem的std::array,不限制长度 template<typename T, typename Elem> struct is_std_array_of : std::false_type {}; template<typename Elem, size_t N> struct is_std_array_of<std::array<Elem, N>, Elem> : std::true_type {}; // 辅助变量模板,C++14及以上可用 template<typename T, typename Elem> constexpr bool is_std_array_of_v = is_std_array_of<T, Elem>::value;
修改后的校验函数
你原来的校验逻辑完全是编译期判断,甚至不需要传入运行时参数:
template<typename T> constexpr bool valid_container_type() { return std::is_same_v<T, std::vector<uint8_t>> || std::is_same_v<T, std::vector<char>> || is_std_array_of_v<T, char> || is_std_array_of_v<T, uint8_t> || std::is_same_v<T, std::string>; }
如果需要保留原有传参的接口,也可以简单包装:
template<typename T> constexpr bool valid_container_type(const T&) { return valid_container_type<T>(); }
C++20简化写法(可选)
如果你的编译环境支持C++20,可以用concept进一步简化代码,不需要单独写类型萃取:
#include <concepts> template<typename T> constexpr bool valid_container_type() { return std::same_as<T, std::vector<uint8_t>> || std::same_as<T, std::vector<char>> || std::same_as<T, std::string> || requires { typename T::value_type; } && std::same_as<T, std::array<typename T::value_type, T{}.size()>> && (std::same_as<typename T::value_type, char> || std::same_as<typename T::value_type, uint8_t>); }
内容的提问来源于stack exchange,提问作者Lars Kakavandi-Nielsen
相关产品推荐
相关产品推荐

