2017-09-30 9 views
13

निम्नलिखित कोड:<string> मिल वेरिएंट के लिए बजना तहत असफल ++ लेकिन नहीं जी ++

variant<string> x = "abc"; 
cout << get<string>(x) << "\n"; 

जी के तहत ठीक काम करता है ++ (संस्करण 7.2)। हालांकि, जब बजना तहत ++ (संस्करण 5.0) libstdc का उपयोग कर ++ संकलित, मैं करने के get विधि में निम्न त्रुटि:

/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.2.0/../../../../include/c++/7.2.0/variant:238:46: fatal error: cannot cast 'std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' to its private base class 'std::__detail::__variant::_Variant_storage<false, std:: 
__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >' 
     return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u); 

यह एक संकलक बग है, या मेरे कोड किसी भी तरह से गैर कानूनी है?

+0

क्या आपने निर्दिष्ट किया है कि 'libC++' मानक लाइब्रेरी कार्यान्वयन के रूप में उपयोग किया जाना चाहिए? आईआईआरसी, क्लैंग डिफ़ॉल्ट रूप से libstdC++ का उपयोग करता है। – StoryTeller

+0

मैं यह नहीं देख सकता कि यहां क्या अवैध है, लेकिन, यदि ऐसा है, तो यह गड़बड़ करने के लिए एक बहुत ही बुनियादी बात होगी ... –

+2

यह देखते हुए कि यह gcc + libstdC++ में काम करता है, clang + libC++ में काम करता है, लेकिन क्लैंग + libstdC++, सबसे संभावित मामला यह है कि यह clang और libstdC++ के बीच एक सूक्ष्म असंगतता है। एक जवाब को इंगित करना चाहिए कि वास्तव में असंगतता क्या है। – hvd

उत्तर

13

यह clang bug 31852 (और यह भी 33222), जिसका प्रजनन जोनाथन Wakely के सौजन्य से बहुत प्रासंगिक दिखना चाहिए के कारण होता है:

template<typename V> auto get(V&) { } 

template<typename> 
class variant 
{ 
    template<typename V> friend auto get(V&); 
}; 

int main() 
{ 
    variant<int> v{}; 
    get(v); // error: ambiguous 
} 

बजना ठीक से दोस्त घोषणाओं है कि प्लेसहोल्डर प्रकार को नहीं पहचानता। कैसे libstdC++ लागू करता है कौन सा ठीक है std::get:

// Returns the typed storage for __v. 
template<size_t _Np, typename _Variant> 
constexpr decltype(auto) __get(_Variant&& __v) 
{ 
    return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u); 
} 

इस variant के एक निजी सदस्य तक पहुँचता है, लेकिन इस समारोह properly declared a friend है:

template<size_t _Np, typename _Vp> 
friend constexpr decltype(auto) __detail::__variant::__get(_Vp&& __v); 

libstdC++ के कार्यान्वयन वैध, बजना बस नहीं लगता है है __get एक है friend

+2

कोई भी कामकाजी कामकाज? – papirrin

+1

मुझे लगता है कि विकास के दौरान libstdC++ की संस्करण शीर्षलेख फ़ाइल के एक संशोधित संस्करण का उपयोग करना सबसे अच्छा और उचित रूप से सुरक्षित वर्कअराउंड है। आपको बस बदलने की जरूरत है मित्र घोषणा और सार्वजनिक रूप से __detail :: _ variant :: _ Variant_base (जो अंतर्निहित संस्करण भंडारण में __get पहुंच प्रदान करता है) से प्राप्त कर रहा है। मैं प्राथमिक संकलक के रूप में जीसीसी का उपयोग करते समय क्लैंग-टिडी से कई त्रुटियों को चुप करने के लिए इसका उपयोग करता हूं और किसी भी दुष्प्रभाव को नहीं देखा है। – Stacker

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