2017-09-13 4 views
16

std::type_indexstd::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(..)값인 인지도를 만들 수 있습니까?

+9

수행하여'이 맵에서 발견되지 않은 경우 failingMap [1]'당신이 기본 항목을 만들 수 있습니다. ':: try_emplace' 사용 예 – Sopel

답변

20

문제는지도의 실제 사용이 아닌 operator[]입니다. 문제는 키가 이 아니고이 발견되면 operator[]이 기본값을 할당하고 std::type_index으로는 불가능한 해당 값에 대한 수정 가능한 참조를 반환합니다. emplace, insert, try_emplace 또는 기본 생성자가 필요없는 다른 수정자를 사용할 수 있습니다.

1

물론 항상 type_info에 대해 nullable 래퍼를 만들 수 있습니다.

#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의 백 포트는 단일 헤더 (C++ 03의 Boost 버전과 함께)에 존재합니다. 훌륭한 대안이 존재하기 때문에 nullable 버전이 과도하다고 믿습니다. 그래도 훌륭한 대답입니다. –

관련 문제