2011-02-07 9 views
11

मुझे मानकों में इस बारे में बिल्कुल यकीन नहीं है।इनलाइन क्वालीफायर प्रोटोटाइप या परिभाषा से उपजी है?

foo.h

#include <iostream> 

inline void foo(); 

void foo() 
{ 
    std::cout << "Foo" << std::endl; 
} 

foo.cpp:

#include "foo.h" 

void baz(); 

int main() 
{ 
    baz(); 
    foo(); 
} 

bar.cpp

#include "foo.h" 

void baz() 
{ 
    foo(); 
} 

मैं इस तरह तीन फ़ाइलें कहना अब, foo की परिभाषा दोनों संकलन इकाइयों foo.o और bar.o में संकलित की जाएगी। अगर मैं इसे सही ढंग से समझता हूं, तो इनलाइन फ़ंक्शंस होने से लिंकर टकराव से बच जाएगा। जी ++ संकलित और लिंक इस ठीक है, लेकिन बजना ++ 2.8 के साथ मैं इस त्रुटि मिलती है:

/tmp/cc-7RdmYP.o: In function `foo()': 
bar.cpp:(.text+0x50): multiple definition of `foo()' 
/tmp/cc-LW3id3.o:foo.cpp:(.text+0x50): first defined here 
collect2: ld returned 1 exit status 

ऐसा नहीं है कि बजना ++ void foo() एक inlined समारोह के रूप में नहीं देखा है लगता है। हालांकि, जब मैं परिभाषा में इनलाइन जोड़ता हूं तो यह ठीक काम करता है।

क्या मुझे void foo() पर इनलाइन जोड़ना है, साथ ही इसे एक इनलाइन फ़ंक्शन के रूप में देखा जाना चाहिए, या यह एक क्लैंग ++ बग है?

+0

मुझे लगता है कि आपका मतलब "परिभाषा" नहीं है, "घोषणा"। – Maxpm

+0

आह, हाँ, मैं उनको मिश्रण करता हूं ...;) – Maister

+0

यह एक दिलचस्प सवाल है। –

उत्तर

2

C++ 0x मसौदा N3225 7.1.2 Function specifiers में कहते हैं:

  • clause 2: A function declaration with an inline specifier declares an inline function
  • clause 4: An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case.

तो, मेरे लिए, ऐसा लगता है कि जीसीसी & बजना गलत सही है, लेकिन अभी भी एक है (पतला) मौका है कि चीजें (हैं?) सी ++ 03 में अलग हैं ..

+1

सी ++ 03 शब्द समान है कि "odr-used" को "केवल" इस्तेमाल किया गया था। – aschepler

+0

@Eugen: खंड 1 भी काफी रोचक लगता है * फ़ंक्शंस-विनिर्देशकों का उपयोग ** ** ** फ़ंक्शन घोषणाओं में ही किया जा सकता है * (मेरा जोर)। –

+0

मुझे लगता है कि बेन वोगेट सही है (शुरुआत में उद्धरण देते समय इसके बारे में नहीं सोचा था)। एक परिभाषा भी एक घोषणा है। मानक कहता है: 'एक ऑब्जेक्ट घोषणा, हालांकि, एक परिभाषा भी है जब तक कि इसमें बाहरी विनिर्देशक न हो और उसके पास कोई प्रारंभकर्ता नहीं है। – sstn

0

आपको दोनों स्थानों पर inline का उपयोग करना होगा।

+4

मुझे मानक में कहीं भी नहीं मिल रहा है जिसके लिए इसकी आवश्यकता है, और वास्तव में, मानक विशेष रूप से उस मामले को अनुमति देता है जहां सदस्य समारोह को घोषणा, या परिभाषा पर 'इनलाइन' घोषित किया जाता है, लेकिन दोनों नहीं (फ़ंक्शन 'इनलाइन' है उस मामले में)। –

+0

शायद मैं अब चीजों को भ्रमित कर रहा हूं, लेकिन 1 99 8 के मानक कहते हैं, "[...] की एक से अधिक परिभाषाएं हो सकती हैं, बाहरी लिंक के साथ इनलाइन फ़ंक्शन, [...] एक कार्यक्रम में प्रदान किया गया है कि प्रत्येक परिभाषा एक अलग में दिखाई देती है अनुवाद इकाई, [...] "(धारा 3.2, खंड 5) – sstn

+0

7.1.2, खंड 1 (1 99 8 फिर से ...) कहता है:" फ़ंक्शन-विनिर्देशक केवल फ़ंक्शन घोषणाओं में उपयोग किए जा सकते हैं। " – sstn

1

मेरा मानना ​​है कि एसए का इरादा ndard हमेशा inline निर्दिष्टकर्ता द्वारा कम से कम एक घोषणा करके inline को फ़ंक्शन बनाने की अनुमति देने के लिए किया गया है, लेकिन पहले inline घोषणा को जोड़ने में बहुत देर हो गई थी, इसके बारे में कुछ अनिश्चितता थी। परिभाषा के बाद बहुत देर हो चुकी थी, या पहली कॉल के बाद?

इसके लिए मेरा तर्क दो गुना है, पहले 7.1.1 में उदाहरण हैं, हालांकि गैर-मानक और मुख्य रूप से स्टोरेज क्लास विनिर्देशकों के बारे में, सुझाव देते हैं कि inline प्रत्येक घोषणा पर आवश्यक नहीं है।

दूसरी बार 2001 से यह दोष रिपोर्ट DR 317 (2005 में मतदान) जो जोड़ती है, "यदि किसी भी फ़ंक्शन की परिभाषा इनलाइन के रूप में अपनी पहली घोषणा से पहले एक अनुवाद इकाई में दिखाई देती है, तो कार्यक्रम खराब हो गया है।" वाक्य। वार्तालाप से यह स्पष्ट है कि यह अनुमान लगाया गया था कि प्रत्येक घोषणा पर inline की आवश्यकता नहीं है, विशेष रूप से inline परिभाषित सदस्य फ़ंक्शन के मामले में, लेकिन कक्षा निकाय के बाहर जहां मूल घोषणा में स्पष्ट inline नहीं था।

(उस दोष रिपोर्ट में मेरा मंत्र भी शामिल है कि inline "एक संकेत से अधिक" है।)

बेशक

, जैसे ही बाहरी लिंकेज के साथ एक समारोह एक इनलाइन समारोह एक अनुवाद इकाई में inline विनिर्देशक बाकी के अनुसार सभी अनुवाद इकाइयों में inline घोषित किया जाना चाहिए सहित एक या अधिक घोषणाओं की वजह से है के रूप में अनुच्छेद 7.1.2/4।

प्रश्न में उदाहरण में मेरा मानना ​​है कि इरादा यह है कि foo एक इनलाइन फ़ंक्शन है और यह मान्य कोड है हालांकि मानक के मानक पाठ से मुझे कम स्पष्ट होना प्रतीत होता है।

4

बाधाएं हैं कि आपका क्लैंग सी 99 इनलाइन अर्थशास्त्र का उपयोग करता है। सी 99 में, यदि आपके कार्यों में से कोई एक "इनलाइन" का उपयोग नहीं करता है या इसमें "बाहरी" शामिल है, तो परिभाषा एक "बाहरी परिभाषा" है, जो प्रोग्राम में केवल एक बार दिखाई दे सकती है। inline in C99 देखें।

सी ++ में, आपका प्रोग्राम ठीक है। क्लैंग एसवीएन में, यह बग तय कर दिया गया है और आपके कार्यक्रम को ठीक काम करना चाहिए।

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