2017-09-13 83 views
16

我正在嘗試創建std::unordered_map,其中std::type_index。下面的代碼片段工作:使用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(..)的值而不是密鑰可以製作一個映射嗎?

+9

做'failingMap [1]'你創建一個默認條目,如果它沒有在地圖上找到。例如使用':: try_emplace' – Sopel

回答

20

問題是operator[],而不是實際使用的地圖。問題是如果密鑰是而不是找到,operator[]將分配一個默認值並返回一個可修改的引用該值,這是不可能的std::type_index。您可以使用emplace,inserttry_emplace或任何其他不需要默認構造函數的修改器。

1

我們當然可以爲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); 
} 

或當然,現在我們已經標準::可選...

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

這是'std :: optional'的好回答,C++ 11的backports存在於一個頭文件中(以及C++ 03的Boost版本)。我真的相信一個可空的版本是過度的,因爲存在着優秀的選擇。仍然,很好的答案。 –

相關問題