2017-05-13 11 views
13

निम्नलिखित कोड अच्छी तरह से संकलित:सी ++ 17 संस्करण <any> वर्ग के अंदर

int main() 
{ 
    variant<any> var; 
    var = 5; 
    cout << any_cast<int>(get<any>(var)) << endl; 
    return 0; 
} 

लेकिन जब मैं variant<any> एक वर्ग के सदस्य के रूप में डाल करने के लिए कोशिश कर रहा हूँ

struct MyClass{ 
    variant<any> var; 
}; 

int main() 
{ 
    MyClass s; 
    return 0; 
} 

यह संकलन नहीं है । क्या मैं कुछ गलत कर रहा हूं या यह कुछ बग है?

मैं जीसीसी 7.1.0

In file included from /home/zak/Projects/Anytest/main.cpp:3:0: 
/usr/local/gcc-7.1/include/c++/7.1.0/variant: In instantiation of ‘struct std::__detail::__variant::__accepted_index<const std::variant<std::any>&, std::variant<std::any>, void>’: 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:911:26: required from ‘constexpr const size_t std::variant<std::any>::__accepted_index<const std::variant<std::any>&>’ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:940:6: required by substitution of ‘template<class _Tp, class> constexpr std::variant<std::any>::variant(_Tp&&) [with _Tp = const std::variant<std::any>&; <template-parameter-1-2> = <missing>]’ 
/home/zak/Projects/Anytest/main.cpp:14:13: required from here 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:559:49: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’ 
     decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()), 
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}] 
     static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First); 
                  ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}] 
    { static void _S_fun(); }; 
        ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:559:49: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’ 
     decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()), 
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}] 
     static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First); 
                  ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}] 
    { static void _S_fun(); }; 
        ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:559:49: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’ 
     decltype(__overload_set<_Types...>::_S_fun(std::declval<_Tp>()), 
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}] 
     static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First); 
                  ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}] 
    { static void _S_fun(); }; 
        ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided 
/usr/local/gcc-7.1/include/c++/7.1.0/variant: In instantiation of ‘constexpr const size_t std::__detail::__variant::__accepted_index<const std::variant<std::any>&, std::variant<std::any>, void>::value’: 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:911:26: required from ‘constexpr const size_t std::variant<std::any>::__accepted_index<const std::variant<std::any>&>’ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:940:6: required by substitution of ‘template<class _Tp, class> constexpr std::variant<std::any>::variant(_Tp&&) [with _Tp = const std::variant<std::any>&; <template-parameter-1-2> = <missing>]’ 
/home/zak/Projects/Anytest/main.cpp:14:13: required from here 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:564:12: error: no matching function for call to ‘std::__detail::__variant::__overload_set<std::any>::_S_fun(const std::variant<std::any>&)’ 
    - decltype(__overload_set<_Types...>:: 
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     _S_fun(std::declval<_Tp>()))::value; 
     ~~~~~~^~~~~~~~~~~~~~~~~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: candidate: static std::integral_constant<long unsigned int, sizeof... (_Rest)> std::__detail::__variant::__overload_set<_First, _Rest ...>::_S_fun(_First) [with _First = std::any; _Rest = {}] 
     static integral_constant<size_t, sizeof...(_Rest)> _S_fun(_First); 
                  ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:541:58: note: no known conversion for argument 1 from ‘const std::variant<std::any>’ to ‘std::any’ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate: static void std::__detail::__variant::__overload_set<_Types>::_S_fun() [with _Types = {}] 
    { static void _S_fun(); }; 
        ^~~~~~ 
/usr/local/gcc-7.1/include/c++/7.1.0/variant:535:19: note: candidate expects 0 arguments, 1 provided 
+3

दिलचस्प शुरुआत, मूल्य प्रारंभिकरण के साथ डिफ़ॉल्ट प्रारंभिक स्थान को बदलना, कोड को जीसीसी पर ठीक संकलित करता है। http://coliru.stacked-crooked.com/a/d45087050b803e45 – StoryTeller

+3

कॉपी कन्स्ट्रक्टर को हटाने से कोड संकलन भी हो जाता है: http://coliru.stacked-crooked.com/a/a7481101122a17a0 –

+1

विजुअल स्टूडियो 2017 के साथ दूसरे उदाहरण को संकलित करना और '/ std: C++ नवीनतम' ध्वज पूरी तरह से काम करता है। या तो जीसीसी गुम हो गया, या एमएसवीसी भाग्यशाली हो गया। मैं आगे परीक्षण करूंगा ... – InternetAussie

उत्तर

10

समस्या MyClass की परोक्ष परिभाषित प्रति निर्माता के साथ है का उपयोग कर रहा है, जब यह प्रकार std::variant<std::any> के सदस्य निर्माण कॉपी करने के लिए कोशिश करता है।

अधिभार संकल्प करने के लिए, संकलक पहले समारोह तर्क जा रहा है एक const std::variant<std::any>& साथ, std::variant के निर्माता टेम्पलेट्स के सभी का दृष्टांत के लिए प्रयास करने की जरूरत है।

template <class T> constexpr variant(T&& t) noexcept(/*...*/); 

यह केवल अधिभार संकल्प में भाग लेता है, तो दूसरों के बीच, अभिव्यक्ति FUN(​std​::​forward<T>(t)) अच्छी तरह से बनाई है, जहां FUN[variant.ctor]/12 के अनुसार उत्पादन किया अतिभारित कार्यों का एक सेट है: हमारे हित के निर्माता इस एक है।

इस मामले में, वहाँ केवल एक ही विकल्प प्रकार (std::any) है, इसलिए वहाँ केवल एक काल्पनिक समारोह FUN, जिनके हस्ताक्षर FUN(std::any) है। अब, संकलक को यह तय करने की आवश्यकता है कि FUN को const std::variant<std::any>& के साथ बुलाया जा सकता है या नहीं। इस प्रक्रिया में, संकलक को यह जानने की जरूरत है कि std::anyconst std::variant<std::any>& के साथ बनाया जा सकता है या नहीं।

यह std::any के निर्माता टेम्पलेट template<class T> any(T&& value); है, जो केवल अधिभार संकल्प में भाग लेता है, तो std::is_­copy_­constructible_­v<VT>true (VTstd::decay_t<T> जा रहा है, और Tconst std::variant<std::any>& जा रहा है) है की इन्स्टेन्शियशन ट्रिगर किया जाएगा।

अब क्रम में देखने के लिए कि VT (यानी std::variant<std::any>) constructible नकल है, संकलक std::variant के निर्माता टेम्पलेट्स के सभी का दृष्टांत के लिए प्रयास करने की जरूरत है ... और यह वह जगह है जहां हम शुरू कर दिया है, और हम एक पाश में फंस रहे हैं ।

यह समझा सकते हैं कि हम क्यों template<class _Tp, class> constexpr std::variant<std::any>::variant(_Tp&&) और __overload_set<std::any>::_S_fun त्रुटि संदेश में (जो समारोह FUN ऊपर उल्लेख किया है से मेल खाती है) देखते हैं, और एक ही गलती क्यों हम देखते हैं कई बार दिखाई दे रहा।

यह एक प्रश्न है कि जीसीसी ऊपर दिए गए लूप से कैसे टूटता है, और प्रोग्राम को ट्वीव करने से त्रुटि को रिपोर्ट करने से जीसीसी को रोक दिया जा सकता है। शायद ये कुछ बग का संकेत हैं।


1. सच पूछिये तो, यह बजाय "एक const std::variant<std::any>&" "प्रकार const std::variant<std::any> के lvalue" होना चाहिए।

2. मानक भी जरूरी है कि इस निर्माता केवल अधिभार संकल्प में भाग लेने जाएगा, यदि is_­same_­v<decay_­t<T>, variant>false है। जीसीसी (libstdC++) बाद में जांचने का विकल्प चुनता है। मुझे नहीं पता कि यह अनुरूप है या नहीं।

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