2011-02-07 18 views
11

Tôi không hoàn toàn chắc chắn về điều này trong các tiêu chuẩn. Nói rằng tôi có ba tác phẩm như thế này:Vòng loại nội tuyến bắt nguồn từ nguyên mẫu hoặc định nghĩa?

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(); 
} 

Bây giờ, định nghĩa cho foo sẽ được biên dịch thành cả hai đơn vị biên dịch foo.o và bar.o. Nếu tôi hiểu nó một cách chính xác, có chức năng nội tuyến sẽ tránh được sự liên kết collition. G ++ biên soạn và các liên kết này chỉ là tốt, nhưng với kêu vang ++ 2.8 Tôi nhận được lỗi này:

/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 

Dường như kêu vang ++ không thấy void foo() như một chức năng inlined. Nó tuy nhiên, làm việc tốt khi tôi thêm nội tuyến để định nghĩa là tốt.

Tôi có phải thêm nội dòng vào void foo() cũng ở đây để nó được xem là chức năng nội tuyến hay là lỗi clang ++?

+0

Tôi nghĩ bạn có nghĩa là "định nghĩa", không phải "tuyên bố". – Maxpm

+0

À, vâng, tôi có xu hướng trộn những thứ đó ...;) – Maister

+0

Đây là một câu hỏi thú vị. –

Trả lời

2

C++ 0X dự thảo N3225 nói trong 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.

Vì vậy, với tôi, nó trông giống như gcc là đúng & kêu vang sai, nhưng vẫn có một (mỏng) cơ hội rằng mọi thứ (khác nhau) khác nhau trong C++ 03 ..

+1

C++ 03 từ ngữ là giống hệt nhau ngoại trừ "odr-sử dụng" chỉ đơn giản là "được sử dụng". – aschepler

+0

@Eugen: khoản 1 có vẻ khá thú vị quá * Chức năng-specifiers có thể được sử dụng ** chỉ ** trong khai báo chức năng * (nhấn mạnh của tôi). –

+0

Tôi nghĩ Ben Voigt là chính xác ở đây (không nghĩ về nó khi trích dẫn ban đầu). Một định nghĩa cũng là một tuyên bố. Các tiêu chuẩn nói: 'Một tuyên bố đối tượng, tuy nhiên, cũng là một định nghĩa, trừ khi nó có chứa các specifier extern và không có initializer.' – sstn

0

Bạn phải sử dụng inline ở cả hai nơi.

+4

Tôi không thể tìm thấy bất cứ đâu trong tiêu chuẩn yêu cầu điều này, và trên thực tế, tiêu chuẩn đặc biệt cho phép trường hợp một hàm thành viên được khai báo 'inline' tại khai báo, hoặc định nghĩa, nhưng không phải cả hai (hàm là' inline' trong trường hợp). –

+0

Có lẽ bây giờ tôi đang gây nhầm lẫn, nhưng tiêu chuẩn năm 1998 nói "Có thể có nhiều hơn một định nghĩa [...], hàm nội tuyến với liên kết ngoài, [...] trong một chương trình với điều kiện mỗi định nghĩa xuất hiện trong một đơn vị dịch, [...] "(mục 3.2, khoản 5) – sstn

+0

7.1.2, khoản 1 (1998 lần nữa ...) cho biết:" Chỉ có thể sử dụng các chỉ số chức năng trong các khai báo hàm. " – sstn

1

Tôi tin rằng ý định của sta ndard luôn cho phép chức năng được thực hiện inline bằng cách có ít nhất một tuyên bố bao gồm số thông số inline nhưng có một số sự không chắc chắn về thời điểm quá trễ để thêm tuyên bố inline đầu tiên. Sau khi định nghĩa quá muộn, hoặc sau cuộc gọi đầu tiên?

Lý do của tôi cho việc này là hai lần, trước tiên là các ví dụ trong 7.1.1, mặc dù không quy định và chủ yếu về các thông số lớp lưu trữ, cho thấy rằng inline không bắt buộc đối với mọi tuyên bố.

Thứ hai báo cáo lỗi này DR 317 từ năm 2001 (bổ sung năm 2005) bổ sung "Nếu định nghĩa của hàm xuất hiện trong đơn vị dịch trước khi khai báo đầu tiên là nội dòng, chương trình không đúng định dạng." kết án. Rõ ràng là từ cuộc trò chuyện rằng nó đã được yêu cầu inline không bắt buộc đối với mọi tuyên bố, cụ thể trong trường hợp hàm thành viên được xác định rõ ràng inline nhưng bên ngoài thân lớp nơi khai báo ban đầu không có rõ ràng inline.

(Báo cáo lỗi đó cũng chứa câu thần chú của tôi rằng inline là "nhiều hơn một gợi ý".)

Tất nhiên, ngay sau khi một hàm với mối liên hệ bên ngoài là một chức năng inline do một hoặc nhiều tờ khai bao gồm inline specifier trong một đơn vị dịch nó phải được khai báo inline trong tất cả các đơn vị dịch theo phần còn lại của đoạn 7.1.2/4.

Trong ví dụ trong câu hỏi tôi tin rằng ý định là foo là một hàm nội tuyến và rằng đó là mã hợp lệ mặc dù văn bản quy chuẩn của tiêu chuẩn dường như tôi ít rõ ràng hơn nó có thể.

4

Tỷ lệ cược là tiếng kêu của bạn sử dụng ngữ nghĩa nội tuyến C99. Trong C99, nếu một trong các hàm của bạn không sử dụng "inline" hoặc không bao gồm "extern", thì định nghĩa là "định nghĩa bên ngoài", chỉ có thể xuất hiện một lần trong chương trình. Xem inline in C99.

Trong C++, chương trình của bạn vẫn ổn. Trong Clang SVN, lỗi này đã được sửa và chương trình của bạn sẽ hoạt động tốt.

Các vấn đề liên quan