2012-05-04 14 views
5

मान लीजिए मैं निम्नलिखित वर्ग टेम्पलेट है:आकार

template<typename T> 
struct Wrapper { 
    T* t_; 
    static void check() { 
    static_assert(sizeof(Wrapper<T> == sizeof(T*), "Illegal assumption"); 
    } 
}; 

मैं सी ++ 03 मानक में एक C99 मानक में देखा और एक गारंटी नहीं मिल सकता है के लिए मेरे इस धारणा में व्यक्त किया static_assert। मैंने इसे कई संकलक विकल्पों का उपयोग करके विजुअल सी ++ 2008 और 2010 (32 बिट) और लिनक्स (64 बिट) पर जीसीसी पर कोशिश की और मेरी धारणा की पुष्टि हुई।

मेरा प्रश्न हैं:

  • मेरी धारणा विजुअल C++ 2008/2010/11 (विंडोज़) के लिए उचित है?
  • जीसीसी 4. * (लिनक्स) के लिए?
  • कंपाइलर झंडे के किसी भी संयोजन के लिए?
  • क्या आप किसी भी कंपाइलर/मंच के बारे में जानते हैं जहां यह धारणा सच नहीं है?

मुझे लगता है कि एक कंपाइलर संरचना में कुछ पैडिंग जोड़ सकता है उदा। डिबगिंग उद्देश्यों के लिए। लेकिन क्या एक कंपाइलर है जो वास्तव में करता है?

संपादित करें: तो तुम यहाँ से पूछा कि मैं क्या हासिल करना चाहते हैं के रूप में:
मैं निम्नलिखित हस्ताक्षर के साथ सदस्य समारोह है:

Someclass* OtherClass::fn(); 

मैं इस तरह हस्ताक्षर बदलना चाहते हैं:

Wrapper<Someclass> OtherClass::fn(); 

यह रैपर कुछ स्मार्ट-पॉइंटर की तरह कार्य करता है, यानी यह सूचक के जीवनकाल की परवाह करता है, इस प्रकार यह दायरे से बाहर होने पर इसे रिलीज़ करता है। चूंकि फ़ंक्शन को एक डीएलएल सीमा में बुलाया जाता है, मैं यह सुनिश्चित करना चाहता हूं कि लौटा हुआ मूल्य (जो अब एक ठोस प्रकार है, न केवल एक गूंगा सूचक) सभी परिस्थितियों में (यानी संकलक सेटिंग्स, आदि) सूचक के समान आकार के रूप में है होने वाला। योजना/आशा डीबग/रिलीज एप्लिकेशन/डीएलएल बिल्ड के सभी संयोजनों का समर्थन करना है।
जैसा कि आप पूछ सकते हैं: नहीं, मैं बूस्ट :: shared_ptr <>, std :: shared_ptr <>, std :: unique_ptr <> और जैसा कि हम डीएल उपयोगकर्ता को बढ़ावा देने का खुलासा नहीं करना चाहते हैं और हम अभी तक सी ++ 11 का समर्थन नहीं करते हैं।

+1

क्या आपने वर्चुअल फ़ंक्शन/विरासत पर विचार किया था? – PlasmaHH

+0

तो ... आप चाहते हैं कि हम उन सभी कंपाइलरों और प्लेटफॉर्म पर आपके लिए कोड का परीक्षण करें? –

+1

नहीं, वह शायद यह जानना चाहता है कि किसी ने पहले से ही कुछ ऐसा किया है और/या यदि यह मानक या कंपाइलर दस्तावेज़ में कहीं और है। – Tibor

उत्तर

3

यदि आप इसे मानना ​​चाहते हैं और आपके पास संकलन-समय की जांच है, तो आगे बढ़ें। संभवतः आपको ऐसा करने से कुछ लाभ मिलता है।

आपको पैडिंग के बारे में कुछ भी गारंटी नहीं है, लेकिन आम तौर पर पैडिंग का उपयोग संरेखण प्राप्त करने के लिए किया जाता है ताकि प्रकार के सरणी में सरणी के प्रत्येक सदस्य (और संरचना के प्रत्येक सदस्य) को ठीक से गठबंधन किया जा सके। एक देशी सूचक आमतौर पर गठबंधन करने का सही आकार होता है, इसलिए पैडिंग की आवश्यकता नहीं होती है, लेकिन आपको इसकी गारंटी नहीं है।

यह ऐसा कुछ नहीं है जिसे आप केवल जीसीसी के साथ जांच सकते हैं - यह लक्ष्य आर्किटेक्चर पर निर्भर करता है, न केवल संकलक।

+0

मैं सिर्फ यह जानना चाहता हूं कि मुझे क्या ख्याल रखना है, मैं किस पर भरोसा कर सकता हूं और मुझे क्या छोड़ना है। – nriedlin

+0

यदि आपकी धारणा सत्य नहीं है तो आप अपने जोर से फायरिंग पर भरोसा कर सकते हैं। आप इस पर भरोसा नहीं कर सकते कि कभी संकलक (या संस्करण) और लक्ष्य के नए संयोजन पर गोलीबारी नहीं कर सकते। –

1

मानक में देख रहे हैं मैं § 9.2 [class.mem]में दो दिलचस्प बिट्स पाया:

17/ दो मानक लेआउट struct (धारा 9) प्रकार लेआउट संगत अगर वे कर रहे हैं गैर-स्थिर डेटा सदस्यों की संख्या और संबंधित गैर-स्थैतिक डेटा सदस्यों (घोषणा आदेश में) में लेआउट-संगत प्रकार (3.9) हैं।

तो, दो struct केवल एक सूचक में उन्हें लेआउट संगत होगा (इस प्रकार यदि अपने दावे इस प्रकार के लिए रखती है, यह सभी प्रकार के लिए रखती है) के साथ।

20/ एक मानक लेआउट struct वस्तु के लिए एक सूचक, उपयुक्त रूप से परिवर्तित एक reinterpret_cast का उपयोग कर, अपनी प्रारंभिक सदस्य के लिए अंक (या यदि वह सदस्य इकाई जिसमें यह रहता है के लिए एक सा मैदान है, तो है) और इसके विपरीत। [नोट: इसलिए मानक-लेआउट स्ट्रक्चर ऑब्जेक्ट के भीतर अज्ञात पैडिंग हो सकती है, लेकिन इसकी शुरुआत में उचित संरेखण प्राप्त करने के लिए आवश्यक नहीं है। -जेंड नोट]

नोट में हम सीखते हैं कि संरचना की शुरुआत में पैडिंग नहीं हो सकती है।


अपने लक्ष्य पर निर्भर करता है, 20/ पर्याप्त हो सकता है। इसका मतलब है कि यह काम करता है:

void check(T* t) { 
    Wrapper<T>* w = reinterpret_cast<Wrapper<T>*>(t); 
    assert(w->t_ == t); 
} 
1

मैं कहूंगा कि आपकी धारणा अधिकांश कंपाइलरों और झंडे के साथ उचित है।

किसी भी टी के लिए, कंपाइलर टी के सरणी बनाने में सक्षम है, जो संगत होने की आवश्यकता है, इसलिए इसे बिना पैडिंग के बनाने में सक्षम होना चाहिए। इस प्रकार, यह आपके स्ट्रक्चर में रखे गए किसी भी पैडिंग को पूरी तरह से वैकल्पिक होगा, ऐसा कुछ भी नहीं हो सकता है।

दूसरी ओर, मुझे लगता है कि सी या सी ++ मानकों में से कोई भी आप जो पूछ रहे हैं उसकी गारंटी देता है। इसके बारे में गारंटी देने के लिए निकटतम इस तथ्य से निकल जाएगा कि सी ++ में यह मानक लेआउट संरचना है, जो सी ++ कंपाइलर को सी संकलक की तरह फ़ील्ड डालने के लिए प्रतिबंधित करता है, इसलिए सदस्यों को बिना किसी संख्या के आरोही क्रम होना चाहिए शुरुआत में पैडिंग - लेकिन सदस्यों और/या अंतिम सदस्य के बाद पैडिंग अभी भी अनुमति है।

नीचे पंक्ति: यदि आपके पास पहले सदस्य के लिए सूचक है, तो आप पॉइंटर से संरचना (या इसके विपरीत) में सुरक्षित रूप से परिवर्तित कर सकते हैं। आप अपने आप पर हैं यदि आप एक की सरणी बनाने और इसमें अनुक्रमणित करने जैसे कुछ करते हैं जैसे कि यह दूसरे की सरणी थी - काम करने की संभावना काफी अच्छी है, लेकिन मुझे पूरा यकीन है कि मानक नहीं है इसकी गारंटी

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