परिभाषित या कॉल करने के लिए की जरूरत है। लेकिन यह विनाशक जैसे विशेष सदस्य कार्यों में से अधिकांश को स्पष्ट रूप से हटा देता है।
union my_union
{
string str;
int a;
};
व्यावहारिक समस्या यह है कि विनाश सी के बिंदु पर ++ जो संघ के ऊपर भागों के मान्य हैं पता नहीं है।
आप टैग किए गए यूनियन का उपयोग करके और सक्रिय ट्रैक ट्रैक रखने और मैन्युअल रूप से उस मामले में विनाश करने के द्वारा इस पर काम कर सकते हैं।
struct tagged_union {
enum active {nothing, string, integer} which_active;
template<active...As>
using actives = std::integral_sequence<active, As...>
using my_actives = actives<nothing, string, integer>;
struct nothingness {};
union my_union
{
nothingness nothing;
std::string str;
int a;
~my_union() {};
} data;
using my_tuple = std::tuple<nothingness, std::string, int>;
template<active which>
using get_type = std::tuple_element_t<(std::size_t)which, my_tuple>;
template<class F>
void operate_on(F&& f) {
operate_on_internal(my_actives{}, std::forward<F>(f));
}
template<class T, class F>
decltype(auto) operate_on_by_type(F&& f) {
return std::forward<F>(f)(reinterpret_cast<T*>(&data));
}
// const versions go here
private:
// a small magic switch:
template<active...As, class F>
void operate_on_internal(actives<As...>, F&& f) {
using ptr = void(*)(my_union*,std::decay_t<F>*);
const ptr table[]={
[](my_union* self, std::decay_t<F>* pf){
std::forward<F>(*pf)(*(get_type<As>*)self);
}...,
nullptr
};
table[which](&data, std::address_of(f));
}
public:
template<class...Args>
tagged_union(Active w, Args&&...args) {
operate_on([&](auto& t){
using T = std::decay_t<decltype(t)>();
::new((void*)std::addressof(t)) T(std::forward<Args>(args)...);
which = w;
});
}
tagged_union():tagged_union(nothing){}
~tagged_union() {
operate_on([](auto& t){
using T = std::decay_t<decltype(t)>();
t->~T();
which=nothing;
::new((void*)std::addressof(t)) nothingness{}; // "leaks" but we don't care
});
}
};
जो मूल रूप से कैसे boost::variant
कुछ की तरह काम करता है, तो सी ++ 11 में लिखा की एक आदिम स्केच है:
तो हम जैसे कुछ मिल सकता है।
इसमें कुछ भारी मोजो शामिल हैं।
उपर्युक्त संकलित नहीं किया गया है, लेकिन डिज़ाइन ध्वनि है। कुछ नाममात्र सी ++ 14 कंपाइलर्स एक पूर्ण लैम्ब्डा के चारों ओर एक पैक का विस्तार करना पसंद नहीं करते हैं, हालांकि, और भी बॉयलरप्लेट की आवश्यकता होगी।
फिर से खोला गया: सी ++ 11 ने संघ में क्या अनुमति दी है, और 'std :: string', दूसरों के बीच, अब विस्तारित है। –
@PeteBecker मुझे वह मिलता है लेकिन क्या यह [इस] में शामिल नहीं है (http://stackoverflow.com/a/3521998/4342498) क्यू से उत्तर? – NathanOliver
आप बाद में वेक्टर से पढ़ने के लिए संघ के किस सदस्य को 'जानना' की योजना बना रहे हैं? –