检测类型是否为关联容器
Detect whether type is associative container
我正在编写一些容器操作函数。通常情况下,一个版本用于类似矢量的容器,如向量、列表、deque、数组等,而另一个版本用于关联容器,如map、multimap、unordered_map等。我想知道检测类是否为关联容器的"最佳方法"是什么。也许像用BOOST_MPL_HAS_XXX_TRAIT_DEF
检测 mapped_type
typedef 的存在?
这是一个编译时测试,因此没有CPU/内存效率方面来选择"最佳方法"。 如果您通过检查带有 boost 的mapped_type
来使其工作,并且适合您的需求,则没有理由寻找任何不同的东西,尽管肯定有无提升的替代方案(例如,请参阅此处)
请注意,虽然set
和unordered_set
被标准视为关联容器,但没有mapped_type
成员 - 如果要包含它们,可以测试key_type
。
我不会走这种假设的方式。要具体并专门化模板。
我这样做:
// is_deque
// ========
template<typename T, typename ... Types>
struct is_deque {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_deque<std::deque<Types...>> {
static constexpr bool value = true;
};
// is_forward_list
// ===============
template<typename T, typename ... Types>
struct is_forward_list {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_forward_list<std::forward_list<Types...>> {
static constexpr bool value = true;
};
// list
// ====
template<typename T, typename ... Types>
struct is_list {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_list<std::list<Types...>> {
static constexpr bool value = true;
};
// vector
// ======
template<typename T, typename ... Types>
struct is_vector {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_vector<std::vector<Types...>> {
static constexpr bool value = true;
};
// map
// ===
template<typename T, typename ... Types>
struct is_map {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_map<std::map<Types...>> {
static constexpr bool value = true;
};
// set
// ===
template<typename T, typename ... Types>
struct is_set {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_set<std::set<Types...>> {
static constexpr bool value = true;
};
// unordered_map
// =============
template<typename T, typename ... Types>
struct is_unordered_map {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_unordered_map<std::unordered_map<Types...>> {
static constexpr bool value = true;
};
// unordered_set
// =============
template<typename T, typename ... Types>
struct is_unordered_set {
static constexpr bool value = false;
};
template<typename ... Types>
struct is_unordered_set<std::unordered_set<Types...>> {
static constexpr bool value = true;
};
// is_sequence_container
// =====================
template <typename T>
struct is_sequence_container {
static constexpr bool value
= is_deque<T>::value
|| is_forward_list<T>::value
|| is_list<T>::value
|| is_vector<T>::value;
};
// is_associative_container
// ========================
template <typename T>
struct is_associative_container {
static constexpr bool value
= is_map<T>::value
|| is_set<T>::value;
};
// is_unordered_associative_container
// ==================================
template <typename T>
struct is_unordered_associative_container {
static constexpr bool value
= is_unordered_map<T>::value
|| is_unordered_set<T>::value;
};
// is_container
// ============
template <typename T>
struct is_container {
static constexpr bool value
= is_sequence_container<T>::value
|| is_associative_container<T>::value
|| is_unordered_associative_container<T>::value;
};
我知道
这个问题是在 5 年前提出的,但这是我所做的,没有任何超出c++11
的要求:
/// @brief container traits
////////////////////////////////////////////////////////////////////////////////
namespace container_traits {
using tc = char[2];
template<typename T> struct is_container {
static tc& test(...);
template <typename U>
static char test(U&&, decltype(std::begin(std::declval<U>()))* = 0);
static constexpr bool value = sizeof(test(std::declval<T>())) == 1;
};
template < typename T > struct is_associative {
static tc& test(...) ;
template < typename U >
static char test(U&&, typename U::key_type* = 0) ;
static constexpr bool value = sizeof( test( std::declval<T>() ) ) == 1 ;
};
}
template < typename T > struct is_container :
std::conditional<(container_traits::is_container<T>::value || std::is_array<T>::value)
&& !std::is_same<T, std::string>::value
&& !std::is_same<T, const std::string>::value, std::true_type, std::false_type >::type {};
template < typename T > struct is_associative :
std::conditional< container_traits::is_container<T>::value && container_traits::is_associative<T>::value, std::true_type, std::false_type >::type {};
////////////////////////////////////////////////////////////////////////////////
/// @brief no std::enable_if_t in c++11
////////////////////////////////////////////////////////////////////////////////
#if __cplusplus <= 201103L
namespace std {
template< bool B, class T = void >
using enable_if_t = typename std::enable_if<B,T>::type;
}
#endif
相关文章:
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 当前不会命中断点。没有调试器目标代码类型的可执行代码与此文件关联
- 关联容器,比较函数不是元素类型的一部分吗?
- 函数类型定义可以与外部"C"相关联吗?
- MISRA C++规则 14-5-1:在与类型关联的命名空间中声明的泛型函数模板的名称
- C ++ STL 关联容器和用户定义类型
- 检测类型是否为关联容器
- 在C API中定义了一个类型,如何将其与命名空间中的C++类相关联
- 使用具有自定义比较类型的关联容器时出现的问题
- 如何将对象与其类型关联
- 用于将静态字符串常量与类型相关联的类型特征模式
- 为什么 c++ 指针 * 与声明的变量相关联,而不是类型
- 隐式返回 0 如何与主的返回类型扣除相关联?
- 文件类型以编程关联和文件位置(Windows)
- 当两个模板的类型相关联时,如何使用策略模板
- 如何打印这种类型map的值map
, int>关联[2]