2011-10-11 45 views
19

C++ Ngôn ngữ tiêu chuẩn khẳng định các thành phần liên quan đến mẫu sau trong thư viện chuẩn:Trong khai báo "std :: vector <X> f();", là "std :: vector <X>" một instantiation?

Các hiệu ứng được xác định ... nếu một loại không đầy đủ được sử dụng như một mẫu đối số khi instantiating một thành phần mẫu, trừ khi được phép đặc biệt cho thành phần đó (C++ 11 §17.6.4.8/2).

Nguyên nhân sau gây ra sự kiện cho mẫu lớp học std::vector?

class X; 
std::vector<X> f(); // Declaration only; we will define it when X is complete 

Để yêu cầu nó một cách khác, trong phần khai báo hàm std::vector<X> f();, là std::vector instantiated với lập luận X? Hoặc, có phải là std::vector<X> không được khởi tạo cho đến khi f() được sử dụng hoặc xác định không?

Tương tự như vậy, nguyên nhân sau đây gây ra sự kiện của mẫu lớp học std::vector?

class X; 
typedef std::vector<X> XVector; // We will complete X before we use XVector 

Trong khi tôi sử dụng std::vector trong các ví dụ này, câu hỏi áp dụng như nhau cho tất cả các mẫu.

+0

Câu trả lời hay sẽ cung cấp tham chiếu đến Tiêu chuẩn ngôn ngữ C++.Tôi đã tìm kiếm thông qua Language Standard nhưng không thể tìm thấy câu trả lời dứt khoát. –

+0

Tôi chưa bao giờ thấy "không xác định" được sử dụng với một phần của quá trình biên soạn trước ... –

+0

Tại sao bạn muốn biết? –

Trả lời

5

§ 14.7.1 \ 1 Implicit instantiation [temp.inst]

Trừ một lớp mẫu chuyên môn đã được một cách rõ ràng instantiated (14.7.2) hoặc rõ ràng chuyên (14.7.3), lớp chuyên môn về mẫu được khởi tạo ngầm khi chuyên môn được tham chiếu trong ngữ cảnh yêu cầu loại đối tượng được xác định hoàn toàn hoặc khi tính đầy đủ của loại ảnh hưởng đến ngữ nghĩa của chương trình. Sự diễn giải ngầm của chuyên môn mẫu lớp gây ra sự khởi tạo ngầm định của các khai báo, chứ không phải của các định nghĩa hoặc đối số mặc định, của các hàm thành viên lớp, các thành viên, thành phần dữ liệu tĩnh và mẫu thành viên; và nó gây ra sự khởi tạo ngầm định của các định nghĩa của các công đoàn ẩn danh của thành viên. Trừ khi một thành viên của một lớp mẫu hoặc mẫu thành viên đã được khởi tạo rõ ràng hoặc một cách rõ ràng, chuyên môn của thành viên là hoàn toàn được khởi tạo khi chuyên môn được tham chiếu trong ngữ cảnh yêu cầu định nghĩa thành viên tồn tại; nói riêng, việc khởi tạo (và mọi tác dụng phụ liên quan) của dữ liệu tĩnh không xảy ra trừ khi thành viên dữ liệu tĩnh được sử dụng trong một cách yêu cầu định nghĩa thành viên dữ liệu tĩnh tồn tại.

§ 8.3.5 \ 9 Chức năng [dcl.fct]

loại sẽ không được định nghĩa lại hoặc tham số loại.Loại tham số hoặc kiểu trả về cho hàm Định nghĩa không được là loại loại không đầy đủ (có thể cv đủ điều kiện) trừ khi định nghĩa được lồng trong đặc tả thành viên cho lớp đó (bao gồm cả định nghĩa trong các lớp lồng nhau được định nghĩa trong lớp).

§ 3.1 \ 2 Khai báo và định nghĩa [basic.def]

Một tuyên bố là một định nghĩa trừ khi nó tuyên bố một chức năng mà không xác thân của hàm (8.4), nó chứa extern chỉ định (7.1.1) hoặc một đặc tả liên kết25 (7.5) và không phải là bộ khởi tạo cũng như một hàm chức năng, nó khai báo một thành phần dữ liệu tĩnh trong định nghĩa lớp học (9.4). , đó là tuyên bố khai báo đục lỗ (7.2), hoặc là khai báo typedef (7.1.3), khai báo sử dụng (7.3.3), khai báo static_assert (khoản 7), khai báo thuộc tính (khoản 7), khai báo trống (Khoản 7), hoặc chỉ thị sử dụng (7.3.4).

Chỉ được khởi tạo nếu đó là yêu cầu. Tôi không thể tìm thấy một định nghĩa rõ ràng ở bất cứ đâu, nhưng câu nói thứ hai nói rằng những tuyên bố đó không phải là định nghĩa, mà dường như giống như tôi.

+0

câu trả lời của @ ybungalobill không còn tồn tại nữa và người ta không thể thấy câu trả lời trừ khi một người dùng là người dùng đại diện 10k +. –

+0

Nó không phải là một định nghĩa, vì vậy câu trả lời của bạn vẫn có thể đúng. Bạn có nghĩa là "Loại tham số hoặc kiểu trả về cho hàm ** định nghĩa ** không phải là loại lớp không đầy đủ (có thể cv đủ điều kiện) trừ khi định nghĩa hàm được lồng trong đặc tả thành viên cho lớp đó (bao gồm các định nghĩa trong các lớp lồng nhau được định nghĩa trong lớp). " được sử dụng để là "Kiểu của một tham số hoặc kiểu trả về cho một khai báo hàm * không phải là một định nghĩa * có thể là một kiểu lớp không đầy đủ." – UncleBens

+0

@UncleBens: Yup, tôi đã bỏ qua từ đó. Tôi đã sao chép câu trả lời vào câu trả lời của mình. –

2

Không, nó không khởi tạo mẫu. Câu trả lời của Mooing Duck cung cấp tất cả các trích dẫn cần thiết, nhưng đây là một số phân tích.

Sự khởi tạo, theo mặc định, không thể xảy ra nếu không có gì tồn tại để yêu cầu loại được xác định hoàn toàn (§14.7.1/1). Các định nghĩa hàm đặc biệt yêu cầu các kiểu hoàn chỉnh (§8.3.5/9), nhưng câu hỏi đặt ra là liệu một số phần khác của tiêu chuẩn cũng đòi hỏi điều này cho các khai báo khác hay không.

Nhưng có một ngoại lệ đặc biệt cho các định nghĩa, mà tiết lộ rằng tờ khai phi nghĩa thực sự là khác nhau:

Loại một tham số hoặc các kiểu trả về cho một định nghĩa chức năng sẽ không phải là một kiểu lớp đầy đủ (có thể cv-đủ điều kiện) trừ khi định nghĩa hàm được lồng trong đặc tả thành viên cho lớp đó (bao gồm các định nghĩa trong các lớp lồng nhau được định nghĩa trong lớp).

Điều gì đặc biệt về định nghĩa chức năng bên trong thông số kỹ thuật của thành viên? Bởi vì một đặc tả thành viên không thể khai báo cùng một hàm hai lần (§9.2/1), và các thành phần chức năng thành viên được xử lý sau tất cả các khai báo thành viên (§3.3.7/1.1). Về cơ bản, định nghĩa hàm thành viên lồng nhau được coi là khai báo trong lần truyền đầu tiên và sau đó là định nghĩa khi toàn bộ đặc tả thành viên đã được xử lý và lớp hoàn tất (§9.2/2). Và §8.3.5/9 quy định rằng một lớp học không đầy đủ được phép cho lần đầu tiên vượt qua, nhưng không cho phép lần thứ hai.

Nó khá hợp lý để thực hiện tìm kiếm toàn diện, dứt khoát về các quy tắc của tiêu chuẩn cho khai báo hàm và instantiations. Nhưng ví dụ này, mặc dù giới hạn các chức năng của thành viên và tính đầy đủ của kiểu kèm theo, có thể được mở rộng hợp lý sang các chức năng và loại khác. Trong mọi trường hợp, đó là bằng chứng khá tốt về sự khác biệt.

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