2017-09-13 53 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, insert, try_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); 
} 

या जाहिर है, अब हम 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 :: वैकल्पिक' के लिए एक अच्छा जवाब है, और सी ++ 11 के बैकपोर्ट्स एक ही शीर्षलेख में मौजूद हैं (साथ ही सी ++ 03 के लिए बूस्ट संस्करण)। मैं ईमानदारी से मानता हूं कि एक निरर्थक संस्करण अधिक है, क्योंकि उत्कृष्ट विकल्प मौजूद हैं। फिर भी, उत्कृष्ट जवाब। –

संबंधित मुद्दे