C++17实现获取连续内存容器值类型的简洁typetrait方法
简化实现方案
C++17完全可以通过组合标准库自带的类型萃取工具大幅简化代码,不需要手动写所有CV限定的指针特化和数组特化:
#include <type_traits> #include <vector> #include <array> template<class T> struct remove_array_like { private: // 先剥离T顶层的CV限定,避免影响后续判断 using DecayedT = std::remove_cv_t<T>; public: // 指针场景:移除指针得到指向类型 if constexpr (std::is_pointer_v<DecayedT>) { using type = std::remove_pointer_t<DecayedT>; } // 数组场景:移除一维数组的长度 else if constexpr (std::is_array_v<DecayedT>) { using type = std::remove_extent_t<DecayedT>; } // 标准连续容器场景:直接取value_type else { using type = typename DecayedT::value_type; } }; // 别名模板方便调用 template<class T> using remove_array_like_t = typename remove_array_like<T>::type;
验证说明
你可以用静态断言验证所有场景都符合要求:
// 指针场景验证 static_assert(std::is_same_v<remove_array_like_t<int*>, int>); static_assert(std::is_same_v<remove_array_like_t<int* const>, int>); static_assert(std::is_same_v<remove_array_like_t<int* volatile>, int>); static_assert(std::is_same_v<remove_array_like_t<int* const volatile>, int>); // 数组场景验证 static_assert(std::is_same_v<remove_array_like_t<int[]>, int>); static_assert(std::is_same_v<remove_array_like_t<int[5]>, int>); // 标准容器验证 static_assert(std::is_same_v<remove_array_like_t<std::array<int, 3>>, int>); static_assert(std::is_same_v<remove_array_like_t<std::vector<int>>, int>);
如果你不想用if constexpr,也可以用偏特化结合条件萃取实现,代码同样比原实现简洁很多:
template<class T, class = void> struct remove_array_like; // 指针特化 template<class T> struct remove_array_like<T, std::enable_if_t<std::is_pointer_v<std::remove_cv_t<T>>>> { using type = std::remove_pointer_t<std::remove_cv_t<T>>; }; // 数组特化 template<class T> struct remove_array_like<T, std::enable_if_t<std::is_array_v<std::remove_cv_t<T>>>> { using type = std::remove_extent_t<std::remove_cv_t<T>>; }; // 容器特化 template<class T> struct remove_array_like<T, std::void_t<typename std::remove_cv_t<T>::value_type>> { using type = typename std::remove_cv_t<T>::value_type; };
内容的提问来源于stack exchange,提问作者user2052436
相关产品推荐
相关产品推荐

