使用 std::type_index 作为地图中的值
Use std::type_index as value in a map
我正在尝试创建一个 std::unordered_map
,其中 值 是 std::type_index
。以下代码段有效:
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
但是这个没有 运行 并抛出错误:
std::unordered_map<int, std::type_index> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
CS2512: 'std::type_index::type_index': no appropriate default constructor available.
我不完全理解这个错误,这些例子中的构造函数有什么区别?是否可以制作一个地图,其中 typeid(..)
是 值 而不是键?
问题是operator[]
,不是地图的实际使用。问题是,如果 未找到 ,operator[]
将分配一个默认值,return 将分配一个对该值的可修改引用,这对于 [=12] 是不可能的=].您可以使用 emplace
、insert
、try_emplace
或任何其他不需要默认构造函数的修饰符。
我们当然可以始终为 type_info
创建一个可为 null 的包装器。
#include <typeindex>
#include <functional>
#include <unordered_map>
#include <cassert>
struct nullable_type_index
{
constexpr nullable_type_index() : ptr_(nullptr) {}
constexpr nullable_type_index(std::type_info const& ti) : ptr_(std::addressof(ti)) {}
constexpr operator bool() const
{
return bool(ptr_);
}
// I have avoided implicit conversion, but it could probably work
// without any surprises.
std::type_info const& get_type_info() const {
assert(ptr_);
return *ptr_;
}
constexpr bool operator==(nullable_type_index const& other) const {
return ptr_ && other.ptr_
? *ptr_ == *other.ptr_
: ptr_ == other.ptr_;
}
private:
std::type_info const* ptr_;
};
std::size_t hash_value(const nullable_type_index& nti)
{
return nti ? 0 : nti.get_type_info().hash_code();
}
bool operator==(nullable_type_index const& l, std::type_info const& r)
{
return l == nullable_type_index(r);
}
bool operator==(std::type_info const& l, nullable_type_index const& r)
{
return nullable_type_index(l) == r;
}
namespace std {
template<>
struct hash<nullable_type_index>
{
std::size_t operator()(nullable_type_index const& arg) const {
return hash_value(arg);
}
};
}
int main()
{
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
std::unordered_map<int, nullable_type_index> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
}
或者当然,现在我们有 std::optional...
int main()
{
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
std::unordered_map<int, std::optional<std::type_index>> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
}
我正在尝试创建一个 std::unordered_map
,其中 值 是 std::type_index
。以下代码段有效:
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
但是这个没有 运行 并抛出错误:
std::unordered_map<int, std::type_index> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
CS2512: 'std::type_index::type_index': no appropriate default constructor available.
我不完全理解这个错误,这些例子中的构造函数有什么区别?是否可以制作一个地图,其中 typeid(..)
是 值 而不是键?
问题是operator[]
,不是地图的实际使用。问题是,如果 未找到 ,operator[]
将分配一个默认值,return 将分配一个对该值的可修改引用,这对于 [=12] 是不可能的=].您可以使用 emplace
、insert
、try_emplace
或任何其他不需要默认构造函数的修饰符。
我们当然可以始终为 type_info
创建一个可为 null 的包装器。
#include <typeindex>
#include <functional>
#include <unordered_map>
#include <cassert>
struct nullable_type_index
{
constexpr nullable_type_index() : ptr_(nullptr) {}
constexpr nullable_type_index(std::type_info const& ti) : ptr_(std::addressof(ti)) {}
constexpr operator bool() const
{
return bool(ptr_);
}
// I have avoided implicit conversion, but it could probably work
// without any surprises.
std::type_info const& get_type_info() const {
assert(ptr_);
return *ptr_;
}
constexpr bool operator==(nullable_type_index const& other) const {
return ptr_ && other.ptr_
? *ptr_ == *other.ptr_
: ptr_ == other.ptr_;
}
private:
std::type_info const* ptr_;
};
std::size_t hash_value(const nullable_type_index& nti)
{
return nti ? 0 : nti.get_type_info().hash_code();
}
bool operator==(nullable_type_index const& l, std::type_info const& r)
{
return l == nullable_type_index(r);
}
bool operator==(std::type_info const& l, nullable_type_index const& r)
{
return nullable_type_index(l) == r;
}
namespace std {
template<>
struct hash<nullable_type_index>
{
std::size_t operator()(nullable_type_index const& arg) const {
return hash_value(arg);
}
};
}
int main()
{
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
std::unordered_map<int, nullable_type_index> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
}
或者当然,现在我们有 std::optional...
int main()
{
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
std::unordered_map<int, std::optional<std::type_index>> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
}