2015-06-23 15 views
10

Tôi tự hỏi tại sao đoạn mã sau làm việc và những gì specifier extern không khi instantiating baz_instance:Truyền một cấu trúc tới một mẫu có const bên ngoài. Extern cho là gì?

struct baz { 
    int value; 
}; 

extern const baz baz_instance = {3}; 

template<baz const& b> 
int foo(){ 
    return b.value; 
} 

int main(){ 
    foo<baz_instance>(); 
    return 1; 
} 

Tại sao mã trên biên dịch ở nơi đầu tiên và tại sao nó không biên dịch nữa nếu extern specifier bị bỏ quên? Trình chỉ định extern làm gì trong ví dụ này?

Trả lời

6

Đây là một trong các phần của tiêu chuẩn đã thay đổi từ C++ 03 thành C++ 11.

Trong C++ 03, [temp.arg.nontype] lượt đọc:

Mẫu đối số cho một tổ chức phi loại, phi mẫu template-tham số sẽ là một trong:

  • [...]
  • [...]
  • địa chỉ của một đối tượng hoặc chức năng với liên kết bên ngoài, bao gồm mẫu chức năng và chức năng template-ids nhưng không bao gồm các thành viên lớp không tĩnh, thể hiện dưới dạng & id thể hiện nơi & là không bắt buộc nếu tên dùng để chỉ một hàm hoặc mảng hoặc nếu tham số mẫu tương ứng là tham chiếu; hoặc
  • [...]

Trong C++ 11, mà đã được cập nhật như là kết quả của issue 1155, mặc dù GCC vẫn có a bug liên quan đến hành vi này:

  • biểu thức liên tục (5.19) chỉ định địa chỉ của đối tượng hoàn chỉnh với thời lượng lưu trữ tĩnh và liên kết bên ngoài hoặc bên trong hoặc chức năng với liên kết bên ngoài hoặc bên trong , bao gồm hàm mẫu và chức năng mẫu-id nhưng không bao gồm thành viên lớp không tĩnh, được biểu thị (bỏ qua dấu ngoặc đơn) làm biểu thức id, biểu thức id là tên của đối tượng hoặc chức năng, ngoại trừ được bỏ qua nếu tên đề cập đến một hàm hoặc mảng và sẽ bị bỏ qua nếu tham số mẫu tương ứng là một tham chiếu; hoặc

Trong C++ 14, đơn giản hơn nữa và thậm chí không đề cập đến liên kết.

Đối với câu hỏi cụ thể của bạn, thông số extern thêm liên kết bên ngoài vào baz_instance. Không có nó, baz_instance có liên kết nội bộ. Trong C++ 03, bạn cần liên kết bên ngoài để có tham số mẫu không kiểu tham chiếu. Trong C++ 11, bạn không còn nữa - vì vậy extern không còn cần thiết nữa và nó biên dịch tốt mà không có nó.

0

Từ khóa extern cho biết rằng biến được xác định trong một đơn vị biên dịch khác (tệp nguồn).

Vì vậy, trong trường hợp của bạn, baznên được định nghĩa trong một tập tin nguồn khác nhau và extern là một cách để nói rằng đây là một biến không được định nghĩa trong tập tin nguồn này, nhưng trong một chương trình khác, và bạn sẽ tìm thấy nó trong biên dịch.

Từ khóa extern có nghĩa là "khai báo không xác định". Nói cách khác, nó là một cách để khai báo một biến rõ ràng, hoặc ép buộc một khai báo không có định nghĩa.

+0

Như bạn có thể thấy từ mã nguồn, baz không được xác định trong tệp nguồn khác. Hơn nữa nó sẽ không giải thích, tại sao thể hiện struct có thể được truyền cho một khuôn mẫu với bên ngoài, nhưng không thể không có bên ngoài. – smoes

+0

Xem chỉnh sửa trong câu trả lời của tôi –

1

Từ 14.3.2.1 các tiểu bang tiêu chuẩn:

Mẫu đối số cho một tổ chức phi loại, phi mẫu template-tham số sẽ là một trong:

  • địa chỉ của một đối tượng hoặc hoạt động với liên kết bên ngoài, bao gồm mẫu chức năng và id mẫu chức năng nhưng không bao gồm các thành viên lớp không tĩnh , được biểu thị là & id-expression, trong đó & là tùy chọn l nếu tên đề cập đến một hàm hoặc mảng hoặc nếu tham số mẫu tương ứng là tham chiếu;

Từ https://stackoverflow.com/a/643927/451600 bởi mweerden

1

Từ khóa extern có nghĩa là nó sẽ có mối liên hệ bên ngoài, nói cách khác là biểu tượng sẽ được xuất khẩu khi các đơn vị dịch sẽ được biên dịch. Vì loại của bạn là const, theo mặc định, nó có liên kết nội bộ (như thể nó đã được khai báo là static). Mẫu không thể phụ thuộc vào các loại chỉ có liên kết nội bộ.

Tôi rất muốn biết lý do tại sao, nhưng có vẻ như nó bị mất đến cát của thời gian: Why did C++03 require template parameters to have external linkage?.

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