2013-05-15 5 views
17

मैं निम्नलिखित कोड में परेशानी आ रही करने के लिए समान होने के बावजूद constexpr:नेस्टेड struct टूटता वैश्विक लोगों

template<typename T> 
constexpr int get(T vec) { 
    return vec.get(); 
} 

struct coord { 
    constexpr int get() const { return x; } 
    int x; 
}; 

struct foo { 
    struct coord2 { 
     constexpr int get() const { return x; } 
     int x; 
    }; 
    constexpr static coord f = { 5 }; 
    constexpr static int g = get(f); // works 

    constexpr static coord2 h = { 5 }; 
    constexpr static int i = get(h); // doesn't work 
}; 

constexpr coord foo::f; 
constexpr foo::coord2 foo::h; 

int main(){} 

अनिवार्य रूप से, get(f) एक निरंतर अभिव्यक्ति माना जाता है, लेकिन get(h) नहीं है। एकमात्र चीज बदल गई है कि कोई वैश्विक संरचना coord का उपयोग करता है, जबकि दूसरा नेस्टेड स्ट्रक्चर coord2 का उपयोग करता है। Structs ' निकायों समान हैं।

ऐसा क्यों है?


जीसीसी त्रुटि:

test.cpp:20:35: error: field initializer is not constant 

बजना त्रुटि:

test.cpp:20:26: error: constexpr variable 'i' must be initialized by a constant expression 
    constexpr static int i = get(h); // doesn't work 
         ^ ~~~~~~ 
test.cpp:8:10: note: undefined function 'get' cannot be used in a constant expression 
    return vec.get(); 
     ^
test.cpp:20:30: note: in call to 'get({5})' 
    constexpr static int i = get(h); // doesn't work 
          ^
test.cpp:13:21: note: declared here 
     constexpr int get() const { return x; } 

उत्तर

17

यह अंततः एक निरंतर अभिव्यक्ति है ...., यह दिखाता है के रूप में आप main() में i ले जाकर देख सकते हैं:

त्रुटि संदेश बहुत स्पष्ट क्या, हो रहा है जो कि अभी तक foo::coord2::get() परिभाषित नहीं है, क्योंकि सदस्य समारोह परिभाषाओं संलग्नित क्लास के अंत तक विलंबित रहे हैं ताकि वे उपयोग कर सकते हैं के सदस्यों को बाद में घोषित कर रहे हैं।

यह आश्चर्य की बात है कि परिभाषा को बाहरीतम कक्षा के अंत तक देरी हो रही है, लेकिन foo::coord2::get()foo::g तक नहीं पहुंच सका तो आप और भी आश्चर्यचकित होंगे।

मानक कंपाइलर, बीटीडब्ल्यू के साथ सहमत है। अनुभाग 9.2p2 का हिस्सा कहते हैं

Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes).

दुर्भाग्य से, यह केवल चलता है कि वर्ग घोषणा के समापन ब्रेस इन टाल क्षेत्रों के लिए पॉइंट-ऑफ-परिभाषा बन जाता है। मेरा मानना ​​है कि यह मानक में एक दोष है कि यह स्पष्ट रूप से यह नहीं कहता है।

यह भी देखें:

+0

@dyp: कि मैं क्या कहा नहीं है? (यह अनुमानित है, यह स्पष्ट नहीं है) –

+0

आह, ठीक है, मैंने उस पैराग्राफ को गलत समझा, क्षमा करें। – dyp

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