2015-10-10 7 views
9

मुझे std::is_constructible<void()>::value के लिए असंगत परिणाम मिल रहे हैं। मानक की मेरी व्याख्या यह है कि यह गलत होना चाहिए। हालांकि, Clang, libC++ और libstdC++ * दोनों के साथ, सच देता है। जीसीसी और एमएसवीसी दोनों झूठे देते हैं। कौन सा परिणाम सही है?std :: is_constructible <void()> :: मान का सही परिणाम क्या है?

Standardese

यहाँ standardese है, N4527 [meta.unary.prop]/7:

को देखते हुए निम्नलिखित समारोह घोषणा:

template <class T> add_rvalue_reference_t<T> create() noexcept; 

एक टेम्पलेट के लिए विधेय हालत विशेषज्ञता is_constructible<T, Args...> संतुष्ट होगा अगर केवल निम्नलिखित चर परिभाषा के लिए अच्छी तरह से गठित किया जाएगा टेड चर t:

T t(create<Args>()...); 

नोट: यह पाठ से सी ++ 11 (N3485), जहां createnoexcept चिह्नित नहीं किया गया था थोड़ा बदल दिया है। हालांकि, इसके लिए लेखांकन करते समय मेरे परीक्षणों के नतीजे नहीं बदले।

टेस्ट केस

यहाँ दोनों प्रकार विशेषता और standardese परिभाषा के अपने न्यूनतम परीक्षण का मामला है:

#include <type_traits> 

static_assert(std::is_constructible<void()>::value, "assertion fired"); 

template<typename T> 
std::add_rvalue_reference_t<T> create() noexcept; 

template<typename T, typename... Args> 
void foo() { 
    T t(create<Args>()...); 
} 

int main() { 
    foo<void()>(); 
} 

परिणाम:

Clang (HEAD, libc++):

  • स्थिर अभिकथन PASSED
  • foo<void()> संकलन नहीं किया

Clang (HEAD, libstdc++) *:

  • स्थिर अभिकथन
  • PASSED
  • foo<void()>

GCC (HEAD, libstdc++) संकलन नहीं किया:

  • स्थिर दावे विफल
  • foo<void()>

MSVC संकलन नहीं था (संस्करण 19 http://webcompiler.cloudapp.net/ के माध्यम से):

  • स्थिर दावे विफल
  • foo<void()> संकलन नहीं था (स्थिर अभिकथन बाहर टिप्पणी की आवश्यकता है)

* __GLIBCXX__ परिभाषित नहीं किया गया है जब क्लैंग का उपयोग -stdlib विकल्प और -stdlib=libstdc++ के साथ किया जाता है। मुझे यकीन है कि libstdC++ वास्तव में उपयोग किया जा रहा है या नहीं। यदि मानक की मेरी व्याख्या सही है, तो मुझे यकीन है कि यह क्लैंग या libC++ के साथ एक बग है या नहीं।

+1

देखें [एलडब्लूजी 2560] (http://wg21.link/lwg2560) और [क्लैंग बग 25513] (https://llvm.org/bugs/show_bug.cgi?id=25513)। –

+0

@ टी.सी., धन्यवाद! यह देखने के लिए अच्छा है। – chris

उत्तर

7

पढ़ना जारी रखें। एक ही पैराग्राफ से:

पहुँच जाँच के रूप में एक संदर्भ T और Args में से किसी के साथ कोई संबंध में अगर किया जाता है। केवल परिवर्तनीय प्रारंभिकरण के तत्काल संदर्भ की वैधता माना जाता है। [नोट: आरंभीकरण के मूल्यांकन में इस तरह के वर्ग टेम्पलेट विशेषज्ञताओं और समारोह टेम्पलेट विशेषज्ञताओं, परोक्ष-परिभाषित प्रकार्य की पीढ़ी, और इतने पर की इन्स्टेन्शियशन के रूप में साइड इफेक्ट हो सकती है। इस तरह की तरफ प्रभाव "तत्काल संदर्भ" में नहीं हैं और परिणामस्वरूप प्रोग्राम खराब हो रहा है। अंत टिप्पणी]

दावे केवल विफल रहता है जब टेम्पलेट निर्माता instantiated है।हालांकि, जैसा कि नोट में मंजूरी दी गई है, यह दावा वैरिएबल परिभाषा के तत्काल संदर्भ में नहीं है जिसे माना जाता है, और इस प्रकार इसकी "वैधता" को प्रभावित नहीं करता है। इसलिए कंपाइलर्स उस परिभाषा को मान्य मान सकते हैं, भले ही वास्तव में void() का निर्माण करने का प्रयास बीमार गठित कार्यक्रम में हो।

ध्यान दें कि कंपाइलर्स को भी अनुमति देने की अनुमति है, _constructible उपज झूठी होने के बजाय, केवल दावे के आधार पर मूल कार्यक्रम को अस्वीकार कर दें।

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