2013-10-03 10 views
6

मैं C++ में विविधता टेम्पलेट का उपयोग करके विभिन्न एक्सेस कुंजियों के साथ एक मानचित्र को कार्यान्वित करने का प्रयास कर रहा हूं।विविधता वाले टेम्पलेट्स का उपयोग करके मल्टीकी मानचित्र

template<class V, class... Krest> 
class MultikeyMap; 

template<class V, class K, class... Krest> 
class MultikeyMap<V, K, Krest...> : protected std::map<K, V>, 
            protected MultikeyMap<V, Krest...> 
{ 
public: 
    template<class T> 
    void insert(const T& t, const V& v) 
    { 
     std::map<T, V>::insert(make_pair(t, v)); 
    } 

    template<class T> 
    const V* find(const T& k) 
    { 
     typedef std::map<T,V> currentMap; 
     currentMap::const_iterator it = currentMap::find(k); 
     return it == currentMap::end() ? 0 : &it->second; 
    } 

}; 

template<class V> 
class MultikeyMap<V> 
{}; 

मैं डालने में iterators वापस नहीं किया था और कोड सरल बनाने के लिए लगता है:

MultikeyMap<int, double, float> map1; // int and double are keys, float is value type 
map1[ 2 ] = 3.5; 
map1[ 5.7 ] = 22; 

MultikeyMap<unsigned long long, int, float, double, int> map2; // more keys, int is value type 
map2[100000000000ULL] = 56; 

// etc... 

क्या मैं अब की तरह दिखता है: क्या मैं प्राप्त करना चाहते हैं इस तरह के वाक्य रचना काम करने के लिए है।

मुझे इस समाधान में दो प्रमुख दोष दिखाई देते हैं।

पहले, मूल्य प्रकार पहले टेम्पलेट तर्क सूची में जाता है। शुरू में मैं

template<class K, class... Krest, class V> 
class MultikeyMap<K, Krest..., V> 

लिखने का प्रयास किया लेकिन संकलक का कहना है कि "अगर एक वर्ग टेम्पलेट आंशिक विशेषज्ञता के लिए एक तर्क एक पैकेट विस्तार है यह अंतिम तर्क होगा"।

दूसरा std :: नक्शे से संरक्षित विरासत है। मैं वास्तव में इसके बजाय संरचना का उपयोग करना चाहूंगा, लेकिन उस स्थिति में मुझे संग्रहीत मानचित्रों तक पहुंचने का कोई तरीका नहीं दिख रहा है। अगर वहाँ एक static_if था, मैं

template<class V, class K, class... Krest> 
class MultikeyMap<V, K, Krest...> : protected MultikeyMap<V, Krest...> 
{ 
public: 
    template<class T> 
    void insert(const T& t, const V& v) 
    { 
     static if(is_same<T,K>::value) 
      m_map.insert(make_pair(t, v)); 
     else 
      MultikeyMap<V, Krest...>::insert(t, v); 
    } 
private: 
    std::map<K,V> m_map; 
}; 

समस्याओं मैंने कहा पर कृपया सलाह लिखेंगे। यदि कोई बेहतर दृष्टिकोण है, तो मुझे सीखने में खुशी होगी।

पढ़ने के लिए धन्यवाद।

+0

'MultikeyMap <अहस्ताक्षरित लंबे, पूर्णांक, पूर्णांक, डबल, int > ':' int' को दो बार कुंजी के रूप में उद्धृत किया गया है, क्या वास्तव में इसका इरादा है? आप कैसे जान रहे हैं कि उपयोगकर्ता पहले या दूसरे 'int' द्वारा देख रहा है या नहीं? साथ ही, यह मेरे लिए अस्पष्ट है कि आप क्या हासिल करने की कोशिश कर रहे हैं; क्या एक मूल्य सभी मानचित्रों में एक बार में उपस्थित होना चाहिए? क्योंकि अगर यह सिर्फ एक मानचित्र में है तो एक बड़ा आम कंटेनर रखने में कोई बात नहीं है। –

+0

@MatthieuM .: बिंदु के लिए धन्यवाद, एक int होना चाहिए। मान अब के लिए एक मानचित्र में मौजूद होना चाहिए, लेकिन बाद में मैं पहले से संग्रहीत मूल्य के लिए एक और कुंजी जोड़ने की क्षमता जोड़ने जा रहा हूं। –

उत्तर

2

आसान लेकिन पूरी तरह से समकक्ष दृष्टिकोण शायद Boost.Bimap या Boost.MultiIndex हैं।

पूर्व एक नक्शा है जहां कुंजी मूल्यों को देख सकते हैं और इसके विपरीत, जबकि उत्तरार्द्ध अधिक सामान्य है: यह एक अनियंत्रित सूचकांक वाला कंटेनर है, दोनों अनुक्रमित ("सूची-जैसी"), यादृच्छिक दोनों -कैस ("वेक्टर-जैसी"), सहयोगी ("नक्शा की तरह") और पहुंच को धोया।

आप Boost.MultiIndex के आस-पास अपने विविध टेम्पलेट्स को लपेटने का प्रयास कर सकते हैं, तो कम से कम आपको सभी सम्मिलन/मिटा तर्क (लेकिन केवल पतली रैपर) को फिर से लागू करने की आवश्यकता नहीं है।

नोट: Boost.MultiIndex प्रकार की एक variadic अनुक्रम की आवश्यकता नहीं है, आप भी प्राथमिक डेटा प्रकार के रूप में एक उपयोगकर्ता परिभाषित वर्ग के विभिन्न डेटा सदस्यों निकालने सदस्य कार्यों के एक variadic अनुक्रम हो सकता है।

2

यहाँ कैसे मैं यह कर देगा:

template<class V, class K, class... Krest> 
class MultikeyMap : MultikeyMap<V, Krest...>, 
        MultikeyMap<V, K> 
{ 
    using ParentMM = MultikeyMap<V, Krest...>; 
    using Parent = MultikeyMap<V, K>; 
public: 
    using ParentMM::insert; 
    using Parent::insert; 

    using ParentMM::find; 
    using Parent::find; 

    using ParentMM::operator[]; 
    using Parent::operator[]; 
}; 

template<class V, class K> 
class MultikeyMap<V, K> 
{ 
    std::map<K, V> k_map; 
public: 
    void insert(const K& k, const V& v) 
    { 
     k_map.insert(std::make_pair(k, v)); 
    } 

    const V* find(const K& k) const 
    { 
     auto it = k_map.find(k); 
     if (it != k_map.end()) 
      return &it->second; 
     return nullptr; 
    } 

    V& operator[](const K& k) 
    { 
     return k_map[k]; 
    } 
}; 

विरासत यहां उपयुक्त लग रहा है, के रूप में यह कई कार्यान्वयन के व्यवहार के संयोजन है। मैंने बेस को निजी बना दिया क्योंकि using घोषणाओं को सदस्यों को दृश्यमान बनाने के लिए किसी भी तरह की आवश्यकता है। केवल बेस केस में सदस्य के रूप में std::map है।

मैं टेम्पलेट तर्कों को उलट करने के लिए परेशान नहीं होने जा रहा हूं, यह std::tuple के लिए उपयोग की जाने वाली एक ही चाल है, बस अपने पसंदीदा एसटीएल कार्यान्वयन को देखें।

संपादित

यहाँ एक ही कोड, तुच्छ परिवर्तन मैंने कहा के साथ है, तो कुंजी प्रकार पैरामीटर में पहले आओ:

template<class Head, class... Tail> 
struct Helper : Helper<Tail...> { 
    using Last = typename Helper<Tail...>::Last; 
}; 

template<class T> 
struct Helper<T> { 
    using Last = T; 
}; 


template<class K, class... Rest> 
class MultikeyMap : MultikeyMap<Rest...>, 
        MultikeyMap<K, typename Helper<Rest...>::Last> 
{ 
    using ParentMM = MultikeyMap<Rest...>; 
    using Parent = MultikeyMap<K, typename Helper<Rest...>::Last>; 

public: 
    using ParentMM::insert; 
    using Parent::insert; 

    using ParentMM::find; 
    using Parent::find; 

    using ParentMM::operator[]; 
    using Parent::operator[]; 
}; 

template<class K, class V> 
class MultikeyMap<K, V> 
{ 
    std::map<K, V> k_map; 
public: 
    void insert(const K& k, const V& v) 
    { 
     k_map.insert(std::make_pair(k, v)); 
    } 

    const V* find(const K& k) const 
    { 
     auto it = k_map.find(k); 
     if (it != k_map.end()) 
      return &it->second; 
     return nullptr; 
    } 

    V& operator[](const K& k) 
    { 
     return k_map[k]; 
    } 
}; 
संबंधित मुद्दे