2015-04-03 8 views
25

में विफल रहता है मुझे constexpr के साथ कुछ परेशानी हो रही है।परिभाषा से पहले constexpr फ़ंक्शन का उपयोग

constexpr int sz = size(); // only size() is a constexpr function 
          // this code is right 

हालांकि किताब एक विशिष्ट उदाहरण नहीं देता: पुस्तक सी ++ प्राइमर कोड की एक पंक्ति को दर्शाता है। तो मैं अपने आप को द्वारा निम्न कोड का प्रयास करें:

#include <iostream> 
constexpr int fun(); 
int main() 
{ 
    constexpr int f = fun(); 
    std::cout << f << std::endl; 
} 
constexpr int fun() 
{ 
    return 3; 
} 

लेकिन मेरे संकलक कहा fun() अनिर्धारित रहता है।

अगर मैं const में constexpr बदलने के लिए, यह अच्छी तरह से काम करता है, और अगर मैं उपयोग करने से पहले constexpr समारोह को परिभाषित करने के लिए अपने कोड बदलने के लिए:

#include <iostream> 
constexpr int fun() 
{ 
    return 3; 
} 
int main() 
{ 
    constexpr int f = fun(); 
    std::cout << f << std::endl; 
} 

यह भी अच्छी तरह से काम करता है। क्या कोई मुझे बताएगा क्यों?

+1

आप किस कंपाइलर का उपयोग करते हैं? – kvorobiev

+0

@kvorobiev clang, linux – icecity96

+0

क्लैंग का कौन सा संस्करण? – kvorobiev

उत्तर

15

constexpr फ़ंक्शन को इसके पहले उपयोग से पहले परिभाषित नहीं किया जाना चाहिए, हालांकि परिभाषा से पहले किए गए किसी भी कॉल का परिणाम निरंतर अभिव्यक्ति नहीं है।

स्रोत: सी ++ मानक मसौदे n4296, अनुभाग 5.20:

एक सशर्त अभिव्यक्तिe, एक कोर निरंतर अभिव्यक्ति जब तक e के मूल्यांकन है सार मशीन के नियमों का पालन, मूल्यांकन करेगा निम्नलिखित भाव में से एक:

  • this, एक constexpr समारोह में छोड़कर या एक constexpr सह nstructor जिसका मूल्यांकन e के हिस्से के रूप में किया जा रहा है;
  • एक शाब्दिक वर्ग के लिए constexpr कन्स्ट्रक्टर के अलावा किसी फ़ंक्शन का आमंत्रण, constexpr फ़ंक्शन, या एक छोटे विनाशक के निहित आमंत्रण [नोट: ओवरलोड रिज़ॉल्यूशन सामान्य-अंत नोट] के रूप में लागू किया गया है;
  • एक अपरिभाषित constexpr फ़ंक्शन या एक अपरिभाषित constexpr कन्स्ट्रक्टर का एक आमंत्रण;
  • ... मसौदा 3485 (खंड 5.19) से

संस्करण:

एक सशर्त अभिव्यक्ति एक कोर निरंतर अभिव्यक्ति है जब तक कि यह के रूप में निम्न में से एक शामिल है एक संभावित मूल्यांकन किए गए उप-अभिव्यक्ति, लेकिन तार्किक और, तार्किक OR, और सशर्त संचालन के उप-अभिव्यक्तियों का मूल्यांकन नहीं किया जाता है [नोट: एक ओवरलोडेड ऑपरेटर फ़ंक्शन का आह्वान करता है।- अंत नोट]:

  • this [ध्यान दें: जब एक निरंतर अभिव्यक्ति का मूल्यांकन, समारोह मंगलाचरण प्रतिस्थापन वर्ग वस्तु के लिए एक सूचक के साथ एक constexpr सदस्य समारोह में this से प्रत्येक घटना बदल देता है। - अंत नोट];
  • एक शाब्दिक वर्ग या constexpr फ़ंक्शन के लिए constexpr कन्स्ट्रक्टर के अलावा किसी फ़ंक्शन का आमंत्रण [नोट: ओवरलोड रिज़ॉल्यूशन सामान्य - अंत नोट के रूप में लागू होता है];
  • एक अपरिभाषित constexpr समारोह की एक मंगलाचरण या एक अपरिभाषित constexpr निर्माता
  • ...

उदाहरण int x2 = s. t(); n2235 में वास्तव में मानकीकरण से पहले किए गए परिवर्तन के कारण मान्य हो गया। हालांकि, constexpr int x2 = s. t(); एक त्रुटि बनी हुई है।

+0

n4296 एक ड्राफ्ट सी ++ स्टैंडअर्ट है। क्या कंपेलर पहले से ही इसका समर्थन करते हैं? – kvorobiev

+1

@kvorobiev: मैं एक मसौदे से उद्धृत कर रहा हूं क्योंकि यह सार्वजनिक है। नियम पहले कुछ ड्राफ्ट पेश किए गए थे, और आधिकारिक मानक का हिस्सा हैं। –

+0

@kvorobiev आप N3337 5.19/2 देख सकते हैं, जो मूल रूप से C++ 11 मानक का अंतिम संस्करण है। जी ++/क्लैंग ++ सी ++ 11 अनुपालन (मामूली अपवादों के साथ) – vsoftco

3

एक निरंतर अभिव्यक्ति फ़ंक्शन को इसके पहले उपयोग से पहले परिभाषित किया जाना चाहिए। यह देखें paper, धारा 4.1 के अंत में।

+0

तो फिर पुस्तक त्रुटि में है? मानक द्वारा अनुमत नहीं होने के बावजूद शायद कुछ संकलक इस वाक्यविन्यास को स्वीकार करते हैं? –

+0

इस [तालिका] के अनुसार (http://wiki.apache.org/stdcxx/C++0xCompilerSupport) कुछ कंपाइलर्स अब constexpr का समर्थन करते हैं और मुझे संदेह है कि उनमें से एक इस वाक्यविन्यास का समर्थन करता है। – kvorobiev

+0

@kvorobiev लेकिन सबसे महत्वपूर्ण कंपाइलर्स काफी सी ++ 11-तैयार हैं, विशेष रूप से g ++/clang ++ में। एमएसवीसी अभी तक नहीं, लेकिन वहां जा रहा है। – vsoftco

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