2008-10-30 17 views
28

मैं एक नक्शा चाहता हूं जिसमें एक समरूप कुंजी प्रकार है लेकिन विषम डेटा प्रकार हैं।आप एक विषम बढ़ावा कैसे बनाते हैं :: मानचित्र?

मैं (छद्म कोड) की तरह कुछ करने के लिए सक्षम होना चाहते हैं:

boost::map<std::string, magic_goes_here> m; 
m.add<int>("a", 2); 
m.add<std::string>("b", "black sheep"); 

int i = m.get<int>("a"); 
int j = m.get<int>("b"); // error! 

मैं डेटा प्रकार के रूप में एक आधार वर्ग के लिए सूचक हो सकता था बल्कि नहीं होगा।

मैंने पहले कभी भी बढ़ावा नहीं दिया है लेकिन फ़्यूज़न लाइब्रेरी को देखा है लेकिन मुझे यह पता नहीं लगा सकता कि मुझे क्या करना है।

आपकी मदद के लिए धन्यवाद।

+2

'boost :: variant' –

+0

यदि आप मानचित्र में सामान भरना चाहते हैं तो सभी संभावित प्रकारों को जानते हैं तो 'boost :: variant' बहुत अच्छा काम करेगा। यदि आप सचमुच किसी प्रकार का चाहते हैं, तो 'बूस्ट :: कोई भी' जाने का तरीका है। – Kurt

उत्तर

34
#include <map> 
#include <string> 
#include <iostream> 
#include <boost/any.hpp> 

int main() 
{ 
    try 
    { 
     std::map<std::string, boost::any> m; 
     m["a"] = 2; 
     m["b"] = static_cast<char const *>("black sheep"); 

     int i = boost::any_cast<int>(m["a"]); 
     std::cout << "I(" << i << ")\n"; 

     int j = boost::any_cast<int>(m["b"]); // throws exception 
     std::cout << "J(" << j << ")\n"; 
    } 
    catch(...) 
    { 
     std::cout << "Exception\n"; 
    } 

} 
+1

cumbersome_cast के बजाय, आप 'std :: decay' का उपयोग कर सकते हैं। –

+0

यह प्रारंभिक [यहां] (http://www.boost.org/doc/libs/1_35_0/libs/fusion/doc/html/fusion/container/map के रूप में मानचित्र को बढ़ावा देने के बजाय std :: मानचित्र का उपयोग नहीं कर रहा है। एचटीएमएल)? – Tab

9

How can I build a <favorite container> of objects of different types?

आप नहीं कर सकते हैं, लेकिन आप नकली यह बहुत अच्छी तरह से कर सकते हैं। सी/सी ++ में सभी सरणी सजातीय हैं (यानी, तत्व सभी एक ही प्रकार के होते हैं)। हालांकि, संकेत की एक अतिरिक्त परत के साथ आप एक विषम कंटेनर की उपस्थिति दे सकते हैं (एक विषम कंटेनर एक कंटेनर है जहां निहित वस्तुएं विभिन्न प्रकार के हैं)।

विषम कंटेनरों के साथ दो मामले हैं।

पहला मामला तब होता है जब आप सभी कंटेनर में स्टोर करना चाहते हैं, वे सार्वजनिक आधार वर्ग से सार्वजनिक रूप से व्युत्पन्न होते हैं। [...]

दूसरा मामला तब होता है जब ऑब्जेक्ट प्रकार अलग होते हैं - वे एक सामान्य बेस क्लास साझा नहीं करते हैं।
यहां दृष्टिकोण एक हैंडल वर्ग का उपयोग करना है। कंटेनर हैंडल ऑब्जेक्ट्स का एक कंटेनर है (मूल्य या पॉइंटर द्वारा, आपकी पसंद; मूल्य से आसान है)। प्रत्येक हैंडल ऑब्जेक्ट जानता है कि कंटेनर में रखे जाने वाले ऑब्जेक्ट्स में से किसी एक को "होल्ड ऑन" (यानी एक पॉइंटर बनाए रखना) कैसे करें। आप या तो एक ही हैंडल क्लास का उपयोग कई अलग-अलग प्रकार के पॉइंटर्स के साथ उदाहरण डेटा के रूप में कर सकते हैं, या हैंडल क्लास का पदानुक्रम जो विभिन्न प्रकारों को छायांकित करता है (कंटेनर को बेस क्लास पॉइंटर्स को संभालने की आवश्यकता होती है)। इस दृष्टिकोण का नकारात्मक पक्ष यह है कि जब भी आप निहित प्रकारों के सेट को बदलते हैं, तो यह रखरखाव के लिए हैंडल क्लास (एसएस) खोलता है। लाभ यह है कि आप मेमोरी प्रबंधन और ऑब्जेक्ट आजीवन की अधिकांश कुरूपता को समाहित करने के लिए हैंडल क्लास (एसएस) का उपयोग कर सकते हैं। इस प्रकार हैंडल ऑब्जेक्ट्स का उपयोग पहले मामले में भी फायदेमंद हो सकता है।

5

यदि आप सीमित प्रकार के प्रकारों को समर्थित करना चाहते हैं, तो Boost.Variant चाल चलाना चाहिए।

5

धन्यवाद डेविड, यही मुझे चाहिए था। यहां कामकाजी समाधान है।

#include <iostream> 
using std::cout; 
using std::endl; 

#include <map> 
#include <boost/any.hpp> 

using boost::any_cast; 
typedef std::map<std::string, boost::any> t_map; 


int main(int argc, char **argv) 
{ 

    t_map map; 
    char *pc = "boo yeah!"; 

    map["a"] = 2.1; 
    map["b"] = pc; 

    cout << "map contents" << endl; 
    cout << any_cast<double>(map["a"]) << endl; 
    cout << any_cast<char*>(map["b"]) << endl; 

    return 0; 
} 
+1

यह 'const char * पीसी =" बू हाँ! "होना चाहिए;' ' –

0

किसी भी निश्चित रूप से काम को बढ़ावा देता है, लेकिन मुझे लगता है कि इंटेल टू टाइप टेक्नोलॉजी का उपयोग मुख्य प्रकार के फ़्यूज़न मानचित्र के रूप में बेहतर समाधान है। कोई प्रकार का क्षरण और संभवतः तेज़

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