检查类型是否为地图
Checking if a type is a map
我有时发现需要编写可以应用于对象容器或此类容器映射的通用例程(即处理映射中的每个容器)。一种方法是为映射类型编写单独的例程,但我认为拥有一个适用于两种输入类型的例程可能更自然且不那么冗长:
template <typename T>
auto foo(const T& items)
{
return foo(items, /* tag dispatch to map or non-map */);
}
执行此标记调度的安全、清洁的方法是什么?
现有的答案测试了std::map
非常具体的属性,要么它恰恰是std::map
的专业化(这对于与std::map
具有相同接口的std::unordered_map
或非标准类型是错误的),要么测试其value_type
完全std::pair<const key_type, mapped_type>
(对于multimap
和unordered_map
都是如此, 但对于具有类似接口的非标准类型为 false)。
这仅测试它是否提供key_type
和mapped_type
成员,并且可以通过operator[]
访问,因此并没有说std::multimap
是mappish:
#include <type_traits>
namespace detail {
// Needed for some older versions of GCC
template<typename...>
struct voider { using type = void; };
// std::void_t will be part of C++17, but until then define it ourselves:
template<typename... T>
using void_t = typename voider<T...>::type;
template<typename T, typename U = void>
struct is_mappish_impl : std::false_type { };
template<typename T>
struct is_mappish_impl<T, void_t<typename T::key_type,
typename T::mapped_type,
decltype(std::declval<T&>()[std::declval<const typename T::key_type&>()])>>
: std::true_type { };
}
template<typename T>
struct is_mappish : detail::is_mappish_impl<T>::type { };
因为is_mappish
具有true_type
或false_type
的"基本特征",所以您可以像这样对其进行调度:
template <typename T>
auto foo(const T& items, true_type)
{
// here be maps
}
template <typename T>
auto foo(const T& items, false_type)
{
// map-free zone
}
template <typename T>
auto foo(const T& items)
{
return foo(items, is_mappish<T>{});
}
或者,您可以完全避免调度,而只是重载地图和非地图的foo
:
template <typename T,
std::enable_if_t<is_mappish<T>{}, int> = 0>
auto foo(const T& items)
{
// here be maps
}
template <typename T,
std::enable_if_t<!is_mappish<T>{}, int> = 0>
auto foo(const T& items)
{
// map-free zone
}
这对我有用,但不是 100% 测试:
template <class T>
struct isMap {
static constexpr bool value = false;
};
template<class Key,class Value>
struct isMap<std::map<Key,Value>> {
static constexpr bool value = true;
};
int main() {
constexpr bool b1 = isMap<int>::value; //false
constexpr bool b2 = isMap<std::vector<int>>::value; //false
constexpr bool b3 = isMap<std::map<int,std::string>>::value; //true
constexpr bool b4 = isMap<std::future<int>>::value; //false
}
这是我想到的:
#include <type_traits>
#include <utility>
namespace detail
{
template <typename T, typename = void>
struct IsMap : std::false_type {};
template <typename T>
struct IsMap<T, std::enable_if_t<
std::is_same<typename T::value_type,
std::pair<const typename T::key_type,
typename T::mapped_type>
>::value>
> : std::true_type {};
}
template <typename T>
constexpr bool is_map = detail::IsMap<T>::value;
namespace { template <bool> struct MapTagImpl {}; }
using MapTag = MapTagImpl<true>;
using NonMapTag = MapTagImpl<false>;
template <typename T>
using MapTagType = MapTagImpl<is_map<T>>;
相关文章:
- 地图计数确实很重要,或者只是检查是否存在
- 是否有任何C++功能可以对地图进行排序?
- 如何检查变量是否是C++中的地图?
- 是否有像地图这样的C++结构,但我得到的不是值的键,而是值的句柄?
- 如何知道地图中的最后一个元素是否被删除?
- 地图是否将元素存储为 std::p air?
- 每个项目的地图是否可以具有不同的尺寸
- std::unordered_map 如何释放使用 malloc 创建的结构.是否需要对地图进行 2 次查询
- 使用聚合初始化时,是否可以将无拷贝置换到地图中
- 如果地图擦除范围内的第一个和最后一个相等,则是否删除该元素
- 如何检查地图中是否存在匹配项
- 有没有办法检查地图是否已在 C++98 中初始化
- EIGEN地图 - 它是否占数据指针的所有权
- 检查最后一个项目是否通过地图密钥存在
- 在迭代地图时向/从地图添加/删除元素是否安全
- C++检查两个地图中是否存在对象
- 是否可以在地图中推回矢量中的值?C++
- 我读了map.erase(map.end());删除地图的最后一个元素。但是最后一个元素是什么?它是否基于元素的插入顺序?
- 检查类型是否为地图
- 将结构存储在地图中;检查地图中是否存在结构