2014-09-27 11 views
8

मैं निम्नलिखित सी ++ 11 कोड (सरलीकृत संस्करण):एक स्थिर constexpr वर्ग सदस्य को कक्षा के बाहर की परिभाषा की आवश्यकता होती है?

struct Info 
{ 
    const char * name; 
    int version; 
}; 

class Base 
{ 
public: 
    const Info info; 
    Base (Info info) : info (info) {} 
}; 

class Derived : public Base 
{ 
public: 
    static constexpr Info info = {"Foobar", 2}; 
    Derived() : Base (info) {} 
}; 

int main() 
{ 
    static Derived derived; 
    return 0; 
} 

जीसीसी 4.9.1 compiles और लिंक इस कोड को ठीक। दूसरी ओर, क्लैंग 3.5.0, एक अनिर्धारित संदर्भ के बारे में शिकायत करता है:

/tmp/test-109c5c.o: In function `main': 
test.cc:(.text+0x1c): undefined reference to `Derived::info' 
test.cc:(.text+0x22): undefined reference to `Derived::info' 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

कौन सा सही है? क्या यह कोड कानूनी है या नहीं? स्थैतिक constexpr सदस्यों (ज्यादातर this question पर आधारित) के नियमों की मेरी समझ यह है कि परिवर्तनीय के पते को केवल तभी किया जाता है जब चर के पते को लिया जाता है। लेकिन मैं व्युत्पन्न :: जानकारी का पता नहीं ले रहा हूं या इसके संदर्भ में कहीं भी इसका उपयोग नहीं कर रहा हूं; मैं केवल बेस कन्स्ट्रक्टर के मूल्य से इसे पास कर रहा हूं।

विभिन्न समाधान है कि मैं मिल गया है:

  • दोनों कंस्ट्रक्टर्स (बेस और व्युत्पन्न) constexpr करें। यह असली कक्षाओं के साथ एक विकल्प हो सकता है या नहीं हो सकता है, जो उदाहरण में लोगों की तुलना में अधिक जटिल हैं। मैं वैसे भी कोशिश करने जा रहा हूँ।
  • स्थिर अवधि के बजाय स्वचालित रूप से मुख्य में व्युत्पन्न के उदाहरण की घोषणा करें। यह वास्तविक प्रोजेक्ट का विकल्प नहीं है: व्युत्पन्न वर्ग एक प्लगइन कार्यान्वयन है, और इसका एक उदाहरण किसी साझा ऑब्जेक्ट में सार्वजनिक प्रतीक के रूप में निर्यात करने की आवश्यकता है।
  • पूरी तरह से व्युत्पन्न :: जानकारी हटाएं और बेस कन्स्ट्रक्टर को इसके बजाय एक ब्रेस-प्रारंभिक अस्थायी ऑब्जेक्ट के साथ कॉल करें, यानी Base ({"Foobar", 2})। यह समाधान काम करेगा, लेकिन यह बदसूरत हो जाता है (मेरी राय में) क्योंकि अधिक सदस्यों को संरचना जानकारी में जोड़ा जाता है।
+1

[वेक्टर :: push_back odr-value का उपयोग करता है, संभावित वर्ग के सदस्य के अनिर्धारित संदर्भ के कारण संभावित डुप्लिकेट) (http://stackoverflow.com/questions/272900/undefined-reference-to-static-class-member) –

+0

डेटा सदस्य के बजाय इसे सदस्य फ़ंक्शन बनाने के बारे में क्या? – imreal

+0

@ πάνταῥεῖ मैं std :: वेक्टर का उपयोग नहीं कर रहा हूं, लेकिन आपके लिंक ने मुझे सही रास्ते पर रखा है। धन्यवाद! –

उत्तर

2

आह, ऐसा लगता है कि समस्या अंतर्निहित Info(const Info &) कॉपी कन्स्ट्रक्टर है। उस निर्माता के संदर्भ में const Info & पास करने के लिए, व्युत्पन्न :: जानकारी का पता लेना आवश्यक है।

जाहिर है कि जीसीसी प्रतिलिपि बनाने वाले को अनुकूलित करने में क्लैंग से अधिक आक्रामक है। अगर मैं -fno-elide-constructors का उपयोग करता हूं, तो जीसीसी भी व्युत्पन्न :: जानकारी के अनिर्धारित संदर्भ के बारे में शिकायत करता है।

किसी भी मामले में, आधार और व्युत्पन्न कन्स्ट्रक्टर को कॉन्स्टेक्स के रूप में घोषित करना मुझे लगता है कि मैं यहां क्या करना चाहता हूं, जो आधार :: जानकारी को संकलित समय पर प्रारंभ किया गया है, बजाय एक अलग व्युत्पन्न :: जानकारी से कॉपी किया गया है रन टाइम

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