在地图中使用std :: type_index作为值

Use std::type_index as value in a map

本文关键字:index type std 地图      更新时间:2023-10-16

我正在尝试创建一个 std::unordered_map,其中 value 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':没有适当的默认构造器可用。

我不完全理解此错误,这些示例中的构造函数有什么区别?是否可以制作 typeid(..) value 而不是密钥的地图?

问题是 operator[],而不是地图的实际使用。问题是,如果键是未找到的operator[]将分配默认值并将可修改的引用返回到该值,而std::type_index是不可能的。您可以使用emplaceinserttry_emplace或任何其他不需要默认构造函数的修饰符。

我们当然可以为type_info创建一个无效的包装器。

#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 ::可选...

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);
}