2015-07-15 13 views
7

जी के साथ है ++ - 5 मैं निम्नलिखित उत्पादनत्रुटि यदि संदर्भ उपस्थित टपल डिफ़ॉल्ट constructible

#include <type_traits> 
#include <tuple> 
int main() 
{ 
    bool b; 
    b = std::is_default_constructible<int>::value; //Compiles, returns true 
    b = std::is_default_constructible<int&>::value; //Compiles, returns false 
    b = std::is_default_constructible< std::tuple<int> >::value; //Compiles, returns true 
    b = std::is_default_constructible< std::tuple<int&> >::value; //Does not compile 
} 

इस is_default_constructible के कार्यान्वयन में एक बग है मिल सकता है?

/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/../../../../include/c++/5.1.0/tuple:105:9: error: reference to type 'int' requires an initializer 
    : _M_head_impl() { } 
+0

त्रुटि संदेश क्या है? –

+0

इसे @MaximEgorushkin में संपादित किया गया :-) – user3559888

+0

मैं सोच रहा हूं कि उस मामले में एक कन्स्ट्रक्टर के शरीर का मूल्यांकन कैसे किया गया था, लेकिन एक साधारण 'टेम्पलेट संरचना परीक्षण {टी टी; परीक्षण(): टी();}; 'मामला। दिलचस्प। – Yakk

उत्तर

7

यह नहींis_default_constructible में एक बग है:

त्रुटि संदेश एक लंबे ढेर में समाप्त होने वाले सूची है। उस प्रकार की विशेषता केवल डिफ़ॉल्ट निर्माण के तत्काल संदर्भ की जांच करने के लिए आवश्यक है, इसे किसी भी सदस्य प्रारंभकर्ताओं का गहराई से मूल्यांकन करने की आवश्यकता नहीं है। यह प्रतिबंध शायद ऐसा है कि इसे SFINAE का उपयोग करके समर्पित कंपाइलर जादू के बिना कार्यान्वित किया जा सकता है। (देखें [meta.unary.prop], esp। p7)।

tuple और pair डिफ़ॉल्ट रचनाकारों को तत्काल संदर्भ (SFINAE- अनुकूल) में विफल होने की आवश्यकता नहीं थी यदि तत्व प्रकार डिफ़ॉल्ट-निर्मित नहीं हो सकता है। यह LWG 2367 ने संबोधित किया गया है, जो tuple डिफ़ॉल्ट निर्माता के लिए निम्नलिखित SFINAE आवश्यकता का परिचय:

टिप्पणी: यह निर्माता अधिभार संकल्प में भाग नहीं करेगा जब तक कि is_default_constructible<Ti>::value सभी i लिए सच है। [...]

इस अतिरिक्त आवश्यकता, एक टपल के डिफ़ॉल्ट निर्माण एक SFINAE के अनुकूल तरीके से असफल चाहिए, जैसे कि is_default_constructible अब tuple के लिए काम करता है, तो तत्व डिफ़ॉल्ट-निर्माण तत्काल संदर्भ में होने चाहिए असफल साथ

(जो संदर्भ प्रकारों के लिए मामला है)।

एलडब्ल्यूजी 2367 वर्तमान में तैयार स्थिति में है; प्रस्तावित संकल्प (अभी तक) जिथब ड्राफ्ट में शामिल नहीं किया गया है। क्यों is_default_constructible गहरा सदस्य initializers का दृष्टांत संबंध है: -


[इस हिस्से

Yakk टिप्पणियों में एक महत्वपूर्ण मुद्दा उठाया विचाराधीन अब भी है?

जहां तक ​​मेरा बता सकते हैं, इस के साथ क्या करना है सशर्त constexpr 'iveness tuple की के डिफ़ॉल्ट निर्माता। is_default_constructible डिफ़ॉल्ट कन्स्ट्रक्टर के त्वरण का कारण बनता है। इसे केवल यह निर्धारित करने के लिए घोषणा को तुरंत चालू करने की आवश्यकता है कि तत्काल संदर्भ में विफलताओं के बिना इस कन्स्ट्रक्टर को बुलाया जा सकता है या नहीं। हालांकि, घोषणा के तत्कालता को constexpr 'uality का निर्धारण करने की आवश्यकता है, और इससे कन्स्ट्रक्टर की परिभाषा का तत्काल कारण बनता है।

एक वर्ग टेम्पलेट जो constexpr के रूप में चिह्नित किया गया है के एक सदस्य समारोह (या निर्माता) केवल सशर्त constexpr है: उन वर्ग टेम्पलेट instantiations के एकमात्र सदस्य कार्यों constexpr जहां शरीर constexpr प्रतिबंध का उल्लंघन नहीं करता होगा। constexpr फ़ंक्शन के अंदर सदस्य प्रारंभकर्ताओं को अनुमति देने के लिए यह देखने के लिए कि कन्स्ट्रक्टर के लिए कन्स्ट्रक्टर के शरीर की तत्काल आवश्यकता है।पर विचार करें:

struct nonconstexpr { nonconstexpr() { std::cout << "runtime\n"; } }; 
struct isconstexpr { constexpr isconstexpr() {} }; 

template<typename T> 
struct wrapper { T t; constexpr wrapper() : t() {} }; 

जब wrapper के डिफ़ॉल्ट ctor instantiating, संकलक क्रम में सदस्य initializers का दृष्टांत को निर्धारित करने के लिए किया जाए या नहीं इस इन्स्टेन्शियशन constexpr किया जाएगा है।

std::tuple के मामले में, यह किसी सदस्य-प्रारंभकर्ता के तत्काल क्षण का कारण बनता है जो संदर्भ ट्यूपल पत्ता (डेटा सदस्य) को मूल्य-प्रारंभ करने का प्रयास करता है। यह एक त्रुटि है, और यह डिफ़ॉल्ट कन्स्ट्रक्टर के मूल तत्काल के तत्काल संदर्भ में नहीं होती है। इसलिए, तत्काल संदर्भ में प्रतिस्थापन विफलता की बजाय यह एक कठिन त्रुटि है।

-]

यह हिस्सा पूरी तरह से मेरे लिए स्पष्ट क्योंकि CWG 1358 अनिवार्य रूप से सभी instantiations constexpr बनाया है, या नहीं, वे वास्तव में मानदंडों को पूरा नहीं है। और वास्तव में, जीसीसी 6.0, निम्न उदाहरण संकलित करने के लिए असफल नहीं है, जबकि जीसीसी 5.1 और बजना 3.7 इसे अस्वीकार:

#include <type_traits> 

template<typename T> 
struct foo 
{ 
    T t; 
    constexpr foo() {} // remove `constexpr` to make it compile everywhere 
}; 

int main() 
{ 
    static_assert(std::is_default_constructible<foo<int&>>{}, "!"); 
} 

राष्ट्रमंडल खेलों 1358 भी हमें बताता है कि क्यों दो दृष्टिकोण के बीच भेद - सशर्त constexpr और उल्लंघन के बावजूद constexpr - महत्वपूर्ण है:

सवाल है कि क्या यह दृष्टिकोण के रूप में इस मुद्दे को 1581 की चर्चा में पैदा हुई - को अभी भी constexpr एक वर्ग टेम्पलेट की एक constexpr समारोह टेम्पलेट या सदस्य समारोह की विशेषज्ञता लेकिन असमर्थ बना एक में लागू किया जा निरंतर संदर्भ - सही है। निहितार्थ यह है कि वर्ग प्रकारों को शाब्दिक के रूप में वर्गीकृत किया जा सकता है लेकिन संकलित समय पर तत्काल नहीं हो सकता है। इस समस्या को आगे बढ़ाने की अनुमति देने के लिए इस समस्या को "समीक्षा" स्थिति में वापस कर दिया गया है।


libc लिए ++, वहाँ बग #21157, जो 2014-10-15 पर हल किया गया है और clang3.6 शाखा में प्रकट होता है। LibstdC++ के लिए, एक बग रिपोर्ट प्रतीत नहीं होती है; यह मुद्दा combined commit on 2015-06-30 में तय किया गया था जो N4387 - Improving Pair and Tuple (Revision 3) लागू करता है जो वर्तमान में किसी भी gcc5 शाखाओं में प्रकट नहीं होता है।

+0

बात यह है कि, 'is_default_constructible <>' आमतौर पर गहरी विफलताओं का खुलासा नहीं होता है। इस मामले में, यह है। 'Tuple' कार्यान्वयन के साथ कुछ करने के लिए। – Yakk

+0

@ यक आह!आप सही हे। यह केवल गलत जवाब देगा ... – dyp

+1

@Yakk ऐसा लगता है कि इसे सशर्त constexpr'iveness oO http://coliru.stacked-crooked.com/a/59356c32a3c764c8 – dyp

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