2014-10-27 12 views
12

के रूप में constexpr फ़ंक्शन पैरामीटर मैं C++ 11 का उपयोग करके कुछ खिलौने कोड के साथ खेल रहा हूं ताकि चीजें कैसे काम करती हैं।टेम्पलेट तर्क

template <int x, int y> 
class add { 
public: 
    static constexpr int ret = x + y; 
}; 

constexpr int addFunc(const int x, const int y) { 
    return add<x,y>::ret; 
} 

int main() { 
    const int x = 1; 
    const int y = 2; 
    cout << add<x,y>::ret << endl; // Works 
    cout << addFunc(1,2) << endl; // Compiler error 
    return 0; 
} 

मैं जीसीसी 4.8.1 का उपयोग कर रहा है और उत्पादन है:
'एक्स' प्रकार के लिए टेम्पलेट तर्क में एक निरंतर अभिव्यक्ति नहीं है 'पूर्णांक इस दौरान मैं निम्नलिखित मुद्दा यह है कि करने के लिए नीचे सरल में आए '
' वाई पूर्णांक '

वास्तव में क्या दो तरीके मैं add::ret गणना करने के लिए कोशिश कर रहा हूँ के बीच अंतर है' प्रकार के लिए टेम्पलेट तर्क में एक निरंतर अभिव्यक्ति नहीं है '? इन दोनों मानों को संकलन समय पर उपलब्ध होना चाहिए।

+3

'constexpr' कार्यों को रनटाइम पर चलाने में सक्षम होना चाहिए। – chris

+1

अच्छा ... हाँ। तो संकलन समय पर इसका मूल्यांकन क्यों नहीं किया जा सकता है? – Danny

+6

विस्तारित करने के लिए: 'constexpr' फ़ंक्शंस रनटाइम पर चलाने में सक्षम होना चाहिए, और जब भी किसी भी मान के साथ बुलाया जाता है तो आपका 'constexpr' फ़ंक्शन विफल हो जाएगा जो संकलन-समय स्थिर नहीं है, इसलिए आपका' constexpr' फ़ंक्शन मान्य नहीं है । जो आप खोज रहे हैं वह वह नहीं है जो 'constexpr' प्रदान करता है, और सी ++ कुछ अन्य रूप में प्रदान नहीं करता है। निकटतम क्या आता है 'int x' और 'int y' टेम्पलेट पैरामीटर के साथ' addFunc 'टेम्पलेट फ़ंक्शन बना रहा है। – hvd

उत्तर

7

आप संकलक को बताते हैं कि addFunc एक कॉन्स्टेक्सर होगा। लेकिन यह पैरामीटर पर निर्भर करता है, जो स्वयं नहीं हैं, इसलिए संकलक पहले से ही उस पर चोक करता है। उन्हें चिह्नित करने का मतलब केवल तभी होता है जब आप उन्हें फ़ंक्शन बॉडी में संशोधित नहीं करेंगे, और इस बिंदु पर आपके द्वारा किए गए विशिष्ट कॉल पर विचार नहीं किया जाता है।

एक तरह से आप संकलक समझते हैं कि आप केवल addFunc के लिए समय स्थिरांक संकलन पारित करने के लिए जा रहे हैं कर सकते हैं नहीं है: पैरामीटर बनाओ एक टेम्पलेट मानकों में ही:

template <int x, int y> 
constexpr int addFunc() { 
    return add<x,y>::ret; 
} 

फिर फोन के रूप में

cout << addFunc<1,2>() << endl; 
5

यदि x और y हमेशा संकलन समय के रूप में निरंतर मूल्यों (अभिव्यक्ति), और क्या अधिक पर उपलब्ध हैं संकलक पता नहीं है, सी ++ 11/14 constexpr समारोह पैरामीटर का समर्थन नहीं करता है, तो वहाँ कोई रास्ता नहीं x और y को टेम्पलेट के लिए पैरामीटर के रूप में इस्तेमाल किया जा सकता है <> addFunc में जोड़ें।

7

उद्देश्य सिर्फ कोड थोड़ा, सी ++ 14 में छोटा करने के लिए आप चर खाका बना सकते हैं यह है:

template <int x, int y> 
constexpr int addVar = x + y; 

cout << addVar<5, 6> << endl; // Works with clang 3.5, fails on GCC 4.9.1 

जीसीसी 5 will also support this

3

constexpr फ़ंक्शन का फ़ंक्शन पैरामीटर निरंतर अभिव्यक्ति नहीं है। फ़ंक्शन constexpr बाहर है (कॉल करने के कारण यह निरंतर अभिव्यक्ति हो सकता है), लेकिन अंदर की गणना constexpr के रूप में होती है क्योंकि वे सामान्य कार्य में होंगी।

टेम्पलेट-तर्कों को निरंतर अभिव्यक्ति की आवश्यकता होती है।

एक सशर्त अभिव्यक्ति एक है: ये है कि अपने कोड में पूरी नहीं की जाती है और इस तरह संकलक त्रुटि ([expr.const]/2, जोर मेरा) का उत्पादन निरंतर भाव के लिए महत्वपूर्ण आवश्यकताओं हैं कोर निरंतर अभिव्यक्ति जब तक यह एक संभावित का मूल्यांकन उपसूचक (3.2) के रूप में निम्न में से एक शामिल है [...]:

- एक lvalue करने वाली rvalue रूपांतरण (4।1) जब तक यह

  • कि एक पूर्ववर्ती आरंभीकरण के साथ एक नॉन-वोलाटाइल स्थिरांक वस्तु को संदर्भित करता है अभिन्न या गणन प्रकार का एक glvalue लिए आवेदन किया है, एक निरंतर अभिव्यक्ति के साथ प्रारंभ, या
  • के glvalue शाब्दिक प्रकार एक गैर अस्थिर वस्तु constexpr के साथ परिभाषित करने के लिए संदर्भित करता है कि, या कि इस तरह के एक वस्तु की एक उप-वस्तु को संदर्भित करता है, या
  • शाब्दिक प्रकार का एक glvalue कि एक गैर अस्थिर अस्थायी वस्तु को संदर्भित करता है जिसका जीवनकाल समाप्त नहीं हुआ है, निरंतर अभिव्यक्ति के साथ प्रारंभ किया गया;

आप उन्हें टेम्पलेट तर्क के रूप में पारित करने के लिए मानकों के आधार पर एक lvalue करने वाली rvalue रूपांतरण आवेदन कर रहे हैं।
पहला बुलेट आइटम लागू नहीं होता है क्योंकि फ़ंक्शन पैरामीटर न तो प्रारंभिक रूप से प्रारंभ होता है और न ही निरंतर अभिव्यक्ति के साथ प्रारंभ किया जाता है, और दूसरा और तीसरा या तो नहीं (विशेष रूप से, फ़ंक्शन पैरामीटर constexpr घोषित नहीं किया जाएगा)।

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