2015-12-15 9 views
18

क्लैंग ++ 3.7.0 के तहत कोड संकलितों का निम्न भाग g ++ 5.3.1 द्वारा अस्वीकार किया गया है। दोनों में -std=c++14 विकल्प है। कौन सा कंपाइलर सही है? कोई भी जानता है कि इस बारे में मानक वार्ता में कहां है? धन्यवाद।constexpr फ़ंक्शन में फेंक

#include <stdexcept> 
using namespace std; 

constexpr int f(int n) { 
    if (n <= 0) throw runtime_error(""); 
    return 1; 
} 

int main() { 
    char k[f(1)]; 
} 

आउटपुट

[hidden] g++ -std=c++14 c.cpp 
c.cpp: In function ‘constexpr int f(int)’: 
c.cpp:7:1: error: expression ‘<throw-expression>’ is not a constant-expression 
} 
^ 
[hidden] clang++ -std=c++14 c.cpp 
[hidden] 
[hidden] g++ -v 
Using built-in specs. 
COLLECT_GCC=/usr/bin/g++ 
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/lto-wrapper 
Target: x86_64-redhat-linux 
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux 
Thread model: posix 
gcc version 5.3.1 20151207 (Red Hat 5.3.1-2) (GCC) 
[hidden] 
[hidden] clang++ -v 
clang version 3.7.0 (http://llvm.org/git/clang.git 2ddd3734f32e39e793550b282d44fd71736f8d21) 
Target: x86_64-unknown-linux-gnu 
Thread model: posix 
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/3.4.6 
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/5.3.1 
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/5.3.1 
Candidate multilib: .;@m64 
Candidate multilib: 32;@m32 
Selected multilib: .;@m64 
+0

मानक नहीं करता है:

constexpr auto foo(int n) -> int { return n <= 0 ? throw runtime_error("") : 1; } 

लेकिन वहाँ एक बेहतर वैकल्पिक हल, अभी भी c++14 constexpr एक्सटेंशन के सभी को बनाए रखना है यह नहीं कहता कि यह फेंक नहीं सकता है, जहां तक ​​मैं –

+0

देख सकता हूं, यह इंगित किया गया था कि इस पर एक जीसीसी बग रिपोर्ट है, कोई काम-आसपास प्रदान नहीं किया गया है। –

उत्तर

15

बजना सही है, तो ध्यान दें HEAD revision of gcc accepts भी इस कोड को स्वीकार करता है। यह एक अच्छी तरह से गठित कंस्ट्रक्शन फ़ंक्शन है, जब तक तर्क (ओं) के लिए मूल्य होता है जो फ़ंक्शन को कोर निरंतर अभिव्यक्ति के रूप में मूल्यांकन करने की अनुमति देता है। आपके मामले में 1 ऐसा मूल्य है।

इस मसौदे में कवर किया जाता है सी ++ 14 मानक खंड 7.1.5 constexpr विनिर्देशक [dcl.constexpr] जो हमें बताता है कि एक constexpr समारोह में अनुमति दी है:

एक constexpr समारोह की परिभाषा संतुष्ट करेगा निम्नलिखित की कमी:

  • यह आभासी नहीं होगा (10.3);

  • इसका रिटर्न प्रकार एक शाब्दिक प्रकार होगा;

  • इसके प्रत्येक पैरामीटर प्रकार एक शाब्दिक प्रकार होगा;

  • अपने कार्य-शरीर करेगा होना = हटाने के लिए, = डिफ़ॉल्ट या एक यौगिक-बयान है कि

    • एक एएसएम परिभाषा शामिल नहीं है,

    • एक गोटो बयान,

    • एक कोशिश-ब्लॉक, या

    • गैर-शाब्दिक प्रकार या स्थैतिक या थ्रेड सेंट के चर की परिभाषा ओरेज अवधि या जिसके लिए कोई प्रारंभिकता नहीं की जाती है।

कोई प्रतिबंध throw पर है और यह भी कहते हैं (जोर मेरा):

एक गैर टेम्पलेट, गैर डिफॉल्ट constexpr समारोह या एक गैर टेम्पलेट के लिए, गैर-डिफॉल्ट, गैर-विरासत कंस्ट्रैक्स कन्स्ट्रक्टर, यदि कोई तर्क मान मौजूद नहीं है तो फ़ंक्शन या कन्स्ट्रक्टर का आमंत्रण एक evalua हो सकता है कोर निरंतर अभिव्यक्ति (5.1 9) के टेड सबएक्सप्रेस, प्रोग्राम बीमार गठित है; कोई निदान आवश्यक है।

और इस अनुच्छेद हम निम्न उदाहरण है नीचे, जो आपके जैसा:

constexpr int f(bool b) 
    { return b ? throw 0 : 0; } // OK 
constexpr int f() { return f(true); } // ill-formed, no diagnostic required 

throwअनुमति नहीं एक कोर निरंतर अभिव्यक्ति है, जो अनुभाग 5.19[expr.const में कवर किया जाता है में है ] अनुच्छेद 2 जो कहता है:

एक सशर्त अभिव्यक्ति ई जब तक ई के मूल्यांकन एक कोर निरंतर अभिव्यक्ति, है सार मशीन (1.9), निम्न भाव

में से एक का मूल्यांकन होगा की नियमों का पालन और निम्नलिखित गोली में शामिल हैं:

  • एक फेंक-अभिव्यक्ति (15.1)।

और इतने f एक कोर निरंतर अभिव्यक्ति जब n <= 0 में प्रयोग करने योग्य नहीं होगा।

अद्यतन

TemplateRex बताते हैं, वहाँ इस के लिए दो जीसीसी कीड़े रिपोर्ट कर रहे हैं:

TemplateRex भी नोट सुधार लागू नहीं कर रहे हैं 5.3.0 पर और केवल ट्रंक में हैं। नहीं, आसपास के काम प्रदान किए जाते हैं।

4

जैसा कि Shafik Yaghmour द्वारा दिखाया गया है यह एक जीसीसी बग है, जो उम्मीद है कि v6 में निश्चित रूप से तय किया जाएगा।

तब तक, आप c++11 constexpr शैली के लिए वापस कर सकते हैं:

// or maybe name it 
// throw_if_zero_or_less 
constexpr auto foo_check_throw(int n) -> void 
{ 
    n <= 0 ? throw std::runtime_error("") : 0; 
} 

constexpr auto foo(int n) -> int 
{ 
    foo_check_throw(n); 

    // C++14 extensions for constexpr work: 
    if (n % 2) 
    return 1; 
    return 2; 
} 
संबंधित मुद्दे