2013-07-15 12 views
6

सी ++ 11 में हम constexpr मिलती है:लागू संकलन समय constexpr

constexpr int foo (int x) { 
    return x + 1; 
} 

यह x एक संकलन समय त्रुटि के एक गतिशील मान के साथ foo का आमंत्रण बनाने के लिए संभव है? यही है, मैं foo बनाना चाहता हूं जैसे कि कोई केवल constexpr तर्कों में गुजर सकता है।

+1

आप इसे हमेशा एक फ़ंक्शन टेम्पलेट में बदल सकते हैं: 'टेम्पलेट int foo() {वापसी x + 1; } ' –

+1

ध्यान दें कि 'कॉन्टेक्सप्र' को आंशिक रूप से यहां दिए गए सभी वाक्य रचनात्मक कामकाजों का सामना करने के लिए बुलाया गया था। – rubenvb

+0

'#define foo (n) foo () 'मेरे लिए व्यवहार्य दिखता है। –

उत्तर

8

एक metafunction के साथ बदलें:

template <int x> struct foo { static constexpr int value = x + 1; }; 

उपयोग:

foo<12>::value 
+0

या बेहतर, इसे 'ऑपरेटर()' दें ताकि यह फ़ंक्शन कॉल जैसा दिखता हो। – rubenvb

+0

@ रूबेनव: यहां तक ​​कि बेहतर, एक परिवर्तनीय टेम्पलेट का उपयोग करें: 'टेम्पलेट int बार = foo :: मान;'। उपयोग: 'बार <12>'। सी ++ 14 में उपलब्ध है। –

+0

ओह ....... केवल। – rubenvb

0

मैं static_assert का प्रयोग करेंगे के रूप में इस उदाहरण

#include<iostream> 

constexpr int foo(int x) { 
     return x+1; 
} 

int main() { 
     // Works since its static 
     std::cout << foo(2) << std::endl; 
     static_assert(foo(2) || foo(2) == 0, "Not Static"); 

     // Throws an compile error 
     int in = 3; 
     std::cout << foo(in) << std::endl; 
     static_assert(foo(in) || foo(in) == 0, "Not Static"); 
} 

अधिक infos के लिए में दिखाया गया है: http://en.cppreference.com/w/cpp/language/static_assert

+0

मेरे पास 'constexpr' के साथ एक कंपाइलर एटीएम नहीं है, लेकिन क्या यह विचार 'static_assert' को सीधे' foo' में डालने के लिए विस्तारित नहीं होगा? जैसे 'constexpr int foo (int x) {static_assert (x == x," स्थिर नहीं है "); वापसी x + 1; } ' –

+1

@ थॉमसएडिंग। आप तब भी कर सकते हैं जब आप रन-टाइम-मूल्यांकन फ़ंक्शन के समान फ़ंक्शन का उपयोग करने की लचीलापन खो देंगे। चूंकि संकलन समय पर 'static_assert' चेक किया गया है, यह रनटाइम को भी प्रभावित नहीं करेगा। –

2

दुर्भाग्यवश, इस बात की कोई गारंटी नहीं है कि constexpr फ़ंक्शन, यहां तक ​​कि सबसे छोटा, संकलक द्वारा मूल्यांकन किया जाएगा जब तक कि पूरी तरह से आवश्यक न हो। यही है, जब तक यह उस स्थान पर प्रकट न हो जहां संकलन समय पर इसकी मान आवश्यक है, उदा। एक टेम्पलेट में। आदेश संकलक संकलन के दौरान मूल्यांकन करने के लिए लागू करने के लिए, आप कर सकते हैं निम्नलिखित:

constexpr int foo_implementation (int x) { 
    return x + 1; 
} 

#define foo(x) std::integral_constant<int, foo_implementation(x)>::value 

और फिर हमेशा की तरह

के रूप में अपने कोड में foo का उपयोग
int f = foo(123); 

इस विधि की अच्छी बात यह है कि यह संकलन समय मूल्यांकन की गारंटी देता है, और आप एक संकलन त्रुटि मिलती है अगर आप एक रन-टाइम चर foo को पारित करेंगे: नहीं तो

int a = 2; 
int f = foo(a); /* Error: invalid template argument for 'std::integral_constant', 
        expected compile-time constant expression */ 

अच्छी बात यह है कि इसे एक मैक्रो की आवश्यकता होती है, लेकिन यदि आप गारंटीकृत संकलन-समय मूल्यांकन और सुंदर कोड दोनों चाहते हैं तो यह वर्तमान में अपरिहार्य लगता है। (हालांकि मुझे गलत साबित होना अच्छा लगेगा!)

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