2016-12-05 9 views
28

सी ++ 1z "constexpr अगर" पेश करेगा - अगर स्थिति के आधार पर शाखाओं में से एक को हटा दिया जाएगा। उचित और उपयोगी लगता है।"constexpr अगर" बनाम "अगर" अनुकूलन के साथ - क्यों "constexpr" की आवश्यकता है?

हालांकि, क्या कॉन्स्टेक्स कीवर्ड के बिना करना संभव नहीं है? मुझे लगता है कि संकलन के दौरान, कंपाइलर को पता होना चाहिए कि संकलन की स्थिति संकलन के समय के दौरान जानी जाती है या नहीं। यदि ऐसा है, तो भी सबसे बुनियादी अनुकूलन स्तर को अनावश्यक शाखा को हटा देना चाहिए।

उदाहरण के लिए (godbolt में देखें: https://godbolt.org/g/IpY5y5):

int test() { 
    const bool condition = true; 
    if (condition) { 
     return 0; 
    } else { 
     // optimized out even without "constexpr if" 
     return 1; 
    } 
} 

Godbolt एक्सप्लोरर शो, कि -O0 साथ भी जीसीसी-4.4.7 संकलन नहीं किया "1 वापसी", तो यह हासिल क्या साथ वादा किया गया था constexpr अगर। जाहिर है कि इस तरह का पुराना कंपाइलर ऐसा करने में सक्षम नहीं होगा जब स्थिति कॉन्सएक्सप्रस फ़ंक्शन का परिणाम हो, लेकिन तथ्य यह है कि: आधुनिक कंपाइलर जानता है कि स्थिति स्थिर है या नहीं और मुझे इसे स्पष्ट रूप से बताने की आवश्यकता नहीं है।

तो सवाल यह है:

क्यों "constexpr" "constexpr अगर" की जरूरत है?

+7

यह केवल अनुकूलन का मामला नहीं है: 'constexpr if' की मृत शाखा को अमान्य होने की अनुमति है, यानी, यह स्वयं पर संकलित नहीं होगा। आपका सवाल हालांकि खड़ा है। – Quentin

उत्तर

38

उदाहरण के माध्यम से व्याख्या करना आसान है। पर विचार करें

struct Cat { void meow() { } }; 
struct Dog { void bark() { } }; 

और

template <typename T> 
void pet(T x) 
{ 
    if(std::is_same<T, Cat>{}){ x.meow(); } 
    else if(std::is_same<T, Dog>{}){ x.bark(); } 
} 

pet(Cat{}); 
pet(Dog{}); 

लागू एक संकलन त्रुटि (wandbox example) ट्रिगर किया जाएगा, क्योंकि if बयान के दोनों शाखाएं हैं अच्छी तरह से गठित किया जाना है। केवल शाखा से मेल खाता है हालत अच्छी तरह से गठित किए जाने की जरूरत है (wandbox example) -

prog.cc:10:40: error: no member named 'bark' in 'Cat' 
    else if(std::is_same<T, Dog>{}){ x.bark(); } 
            ~^
prog.cc:15:5: note: in instantiation of function template specialization 'pet<Cat>' requested here 
    pet(Cat{}); 
    ^
prog.cc:9:35: error: no member named 'meow' in 'Dog' 
    if(std::is_same<T, Cat>{}){ x.meow(); } 
           ~^
prog.cc:16:5: note: in instantiation of function template specialization 'pet<Dog>' requested here 
    pet(Dog{}); 
    ^

pet बदलने if constexpr

template <typename T> 
void pet(T x) 
{ 
    if constexpr(std::is_same<T, Cat>{}){ x.meow(); } 
    else if constexpr(std::is_same<T, Dog>{}){ x.bark(); } 
} 

उपयोग करने के लिए केवल शाखाओं parseable होने की आवश्यकता है।

टुकड़ा

pet(Cat{}); 
pet(Dog{}); 

संकलन और काम होगा अपेक्षा के अनुरूप।

+1

धन्यवाद। "पारदर्शी" और "अच्छी तरह से गठित" के बीच भेद मुझे पहले छोड़ दिया :-) – MateuszL

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