2017-09-13 8 views
16

の値std::type_indexであるstd::unordered_mapを作成しようとしています。次のスニペットは動作します:マップの値としてstd :: type_indexを使用します

std::unordered_map<std::type_index, int> workingMap; 
workingMap[typeid(int)] = 1; 
workingMap[typeid(char)] = 2; 

しかし、実行していないこの1つはエラースロー:私は完全にこのエラーを理解していない

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では不可能です。 emplaceinserttry_emplace、またはデフォルトコンストラクタを必要としないその他の修飾子を使用できます。

1

もちろん、常に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ている::オプション...

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のバックポートは単一ヘッダ(C++ 03のBoostバージョンと同様)に存在します。優れた選択肢が存在するので、nullableバージョンが過剰であると正直に信じています。それでも、素晴らしい答え。 –

関連する問題