2017-10-20 33 views
15

निम्नलिखित कोड पर विचार करें:वैराडिक कटौती गाइड जी ++ द्वारा नहीं लिया गया है, जो क्लैंग ++ द्वारा लिया गया है - जो सही है?

template <typename... Types> 
struct list 
{ 
    template <typename... Args> 
    list(Args...) 
    { 
     static_assert(sizeof...(Types) > 0); 
    } 
}; 

template <typename... Args> 
list(Args...) -> list<Args...>; 

int main() 
{ 
    list l{0, 0.1, 'a'}; 
} 

मैं उम्मीद करेंगे decltype(l)list<int, double, char> किया जाना है। दुर्भाग्य से, जी ++ 7.2 और जी ++ ट्रंक स्थिर दावे में विफल रहता है। क्लैंग ++ 5.0.0 और क्लैंग ++ ट्रंक संकलित और अपेक्षा के अनुसार काम करें।

godbolt.org conformance view

यह एक जी ++ बग है? या क्या कोई कारण है कि कटौती मार्गदर्शिका का पालन नहीं किया जाना चाहिए?

template <typename... Args, 
      typename = std::enable_if_t<sizeof...(Args) == sizeof...(Types)>> 
list(Args...) 
{ 
    static_assert(sizeof...(Types) > 0); 
} 

godbolt.org conformance view

+0

मैं अपने कोड बीमार का गठन किया जा सकता है ... 'sizeof ... (प्रकार) के लिए लगता है == 0' आपकी टेम्प्लेटेड निर्माता का कोई व्यवहार्य इन्स्टेन्शियशन है ... –

+0

मैं कुछ भी रूप में देखते के लिए संघर्ष कर रहा हूँ एक जीसीसी बग के अलावा। make_list() फ़ंक्शन की पिछली विधि का उपयोग ठीक काम करता है। https://godbolt.org/g/vag3rD –

+0

@ रीचर्डहोड्स स्वाभाविक रूप से आपकी विधि g ++ के साथ 'सूची <> 'को तुरंत चालू करने का प्रयास नहीं करता है। –

उत्तर

10

यह gcc bug 80871 है:


निर्माता पर एक SFINAE बाधा जोड़ने वांछित व्यवहार प्रदान करने के लिए लगता है। मुद्दा हम कटौती के लिए उम्मीदवारों के इस सेट के साथ खत्म होता है,:

template <class... Types, class... Args> 
list<Types...> __f(Args...); // constructor 

template <class... Args> 
list<Args...> __f(Args...); // deduction-guide 

दोनों वैध (Types... पहले मामले में के रूप में खाली मान सकते हैं), लेकिन कॉल यहाँ अस्पष्ट होना चाहिए - न की तुलना में अधिक विशिष्ट है अन्य। Types... यहां ऑर्डर करने में भाग नहीं लेता है (उदाहरण के समान [temp.deduct.partial]/12 में)। तो सही व्यवहार अगले tiebreaker पर आगे बढ़ना है, जो favors deduction-guides है। इसलिए, यह list<int, double, char> होना चाहिए।

हालांकि, जीसीसी का व्यवहार कन्स्ट्रक्टर का पक्ष लेना है, इसलिए static_assert ट्रिगर Types... वास्तव में उस स्थिति में खाली होगा।

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

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