2013-07-18 4 views
6

मैं एक संघ बनाने के लिए है, लेकिन संघ के 2 सदस्य एक ही प्रकार के लिए होता है की जरूरत है, इस प्रकार मैं उन्हें पहचान करने के लिए एक तरह से की जरूरत है। OCaml में उदाहरण के लिए:टैग की गईं यूनियनों सी में (उर्फ संस्करण) ++ एक ही प्रकार के एक से अधिक बार

type A = 
    | B of int 
    | C of float 
    | D of float 

Boost.Variant इस मामले का समर्थन करने के प्रतीत नहीं होता है, वहाँ एक ज्ञात पुस्तकालय जो कि समर्थन करता है, है?

+3

दो समान प्रकार के क्यों? एक संघ के केवल एक सदस्य का इस्तेमाल किसी भी समय किया जा सकता है। – hmjd

+2

मुझे पता है लेकिन ऐसे मामले हैं जब आप सदस्य को विचलित करना चाहते हैं भले ही उनके पास समान अंतर्निहित प्रकार हो। एक छोटा सा उदाहरण एक इंप्रप्रस प्रकार होगा जिसमें int के इंटकॉन्स्ट int और Int intututable int। – maattdd

+2

लेकिन कहीं और कुछ ध्वज होना चाहिए (जिसमें 'struct' या 'class' शामिल है) जो इंगित करता है कि संघ का कौन सा सदस्य _active_ है? इसका उपयोग अतिरिक्त आवश्यक अर्थ प्रदान करने के लिए किया जा सकता है। – hmjd

उत्तर

5

यदि आप ऐसा करना चाहते हैं, तो मुझे लगता है कि आपका सबसे अच्छा विकल्प एक struct जो तब बढ़ावा संस्करण उचित यात्रा की सुविधा देता है में एक ही बल्कि अलग-प्रकार रैप करने के लिए है:

struct Speed 
{ 
    float val_; 
}; 

struct Darkness 
{ 
    float val_; 
}; 

आप BOOST_STRONG_TYPEDEF उपयोग करने के लिए स्वचालित रूप से ऐसा करने में सक्षम हो सकता है, लेकिन मुझे यकीन है कि यह एक संघ में इस्तेमाल के लिए कानूनी प्रकार उत्पन्न करने के लिए (हालांकि यह शायद एक संस्करण में ठीक होगा) की गारंटी है नहीं कर रहा हूँ।

2

C++ यहाँ कोड:

http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_storage/pack/container_one_of_maybe.hpp

सही मायने में यह डुप्लिकेट प्रकार हो सकता है कि किसी टैग की संघ है। एक अच्छी सुविधा टैग्स गणना हो सकती है; इसलिए, टैग सार्थक नाम हो सकते हैं।

दुर्भाग्य से, संकलन समय लागत कार्यान्वयन पुनरावर्ती विरासत का उपयोग करता है क्योंकि, बहुत बुरा, मुझे लगता है है। ओटीओएच, संकलन समय लागत को कम करने के लिए शायद संकलक को एक तरह से समझेंगे।

ओटीओएच, यदि आप बूस्ट :: संस्करण के साथ चिपकना चाहते हैं, तो आप मार्क बी के सुझाव के अनुसार टाइप कर सकते हैं। हालांकि, मार्क बी के वर्णनात्मक वर्ग के नामों के बजाय, जिसके लिए कुछ विचारों की आवश्यकता है, आप fusion::pair<mpl::int_<tag>,T_tag> का उपयोग कर सकते हैं जहां T_tag स्रोत fusion::vector में टैग-वें तत्व है। IOW:

variant 
< fusion::pair<mpl::int_<1>,T1> 
, fusion::pair<mpl::int_<2>,T2> 
... 
, fusion::pair<mpl::int_<n>,Tn> 
> 

संलयन डॉक्स के रूप में:

http://www.boost.org/doc/libs/1_55_0/libs/fusion/doc/html/fusion/support/pair.html

कहते हैं, fusion::pair केवल 2 टेम्पलेट तर्क के लिए जगह आवंटित; इसलिए, इसे boost::variant<T1,T2,...,Tn> से अधिक कक्ष नहीं लेना चाहिए।

एचटीएच।

-regards, लैरी

1

आप नहीं इस समय लेकिन C++17's implementation of std::variant सौभाग्य से यह अनुमति देता है सकते हैं:

एक संस्करण एक बार से एक ही प्रकार के और अधिक धारण करने के लिए, और अलग ढंग से सीवी योग्य धारण करने के लिए अनुमति दी है एक ही प्रकार के संस्करण।

बढ़ावा संस्करण के साथ विपरीत, आप सूचकांक द्वारा मूल्यों को प्राप्त कर सकते हैं, कुछ इस तरह (परीक्षण नहीं):

// Construct a variant with the second value set. 
variant<string, string, string> s(std::in_place_index<1>, "Hello"); 
// Get the second value. 
string first = std::get<1>(s); 

माइकल पार्क a C++14 implementation of C++17's std::variant लिखा है।

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