2013-04-24 21 views
7

Lưu ý: Tôi đã xem here và tôi không nghĩ câu trả lời là đúng.Hiển thị ngầm định các mẫu chức năng khi lấy địa chỉ

Các quy tắc điều chỉnh việc diễn giải hàm ngầm tiềm ẩn khi lấy địa chỉ của chúng là gì? 14.7.1/9 của n3242 nói điều này:

An thực hiện sẽ không ngầm nhanh chóng một hàm mẫu, một mẫu thành viên, một hàm thành viên không ảo, một lớp học thành viên, hoặc một thành viên dữ liệu tĩnh của một lớp mẫu mà không yêu cầu instantiation.

Bây giờ, chắc chắn không bắt buộc phải có định nghĩa chức năng để lấy địa chỉ của nó. Chúng ta có thể lấy địa chỉ của các hàm được khai báo về phía trước và có chúng được định nghĩa trong một đơn vị dịch thuật khác.

Đó là trường hợp, tôi không biết khi nào cần thiết. Tuy nhiên, trình biên dịch dường như có ý tưởng riêng của họ. Thử nghiệm trên GCC và VC, dưới đây là một vài ví dụ:

template <typename T> void CallBanana() { T::Banana(); } 
template <typename T> void CallUnimpl(); 

template <typename T> 
struct S { 
    static void CallBanana() { T::Banana(); } 
    static void CallOrange() { T::Orange(); } 
    static void CallUnimpl(); 
}; 

struct B { static void Banana() {} }; 

int main() { 
    (void)(&CallBanana<void>); // 1 
    (void)(&CallUnimpl<void>); // 2 
    (void)(&S<void>::CallBanana); // 3 
    (void)(&S<void>::CallOrange); // 4 
    (void)(&S<void>::CallUnimpl); // 5 
    (void)(&S<B>::CallBanana); // 6 
} 

Chúng nên được nhận xét từng người một để xem hiệu ứng.

GCC 4.7 tested here sẽ khiếu nại khoảng 1, 3 và 4. Vì vậy, nó sẽ khởi tạo tất cả các định nghĩa nếu chúng tồn tại.

VC 2010 (không kiểm tra trực tuyến, xin lỗi) instantiates 3 và 4, nhưng không nhanh chóng 1.

Clang 3,0 tested here có hành vi tương tự như VC 2010.

Không biên dịch phàn nàn về 2 hoặc 5, mà tôi mong đợi. Tôi hy vọng nó sẽ không liên kết nếu tôi thực sự sử dụng những con trỏ mặc dù.

Trên tất cả các trình biên dịch, 6 biên dịch. Tôi mong đợi điều này, nhưng nó được dự định để cho thấy rằng toàn bộ mẫu lớp không được khởi tạo (như được yêu cầu trong câu trả lời cho câu hỏi khác) chỉ vì tôi lấy địa chỉ của một hàm duy nhất. Nếu toàn bộ khuôn mẫu được khởi tạo, thì S :: CallOrange sẽ không biên dịch, vì B không chứa hàm Orange.

Vì vậy, tôi tự hỏi liệu có ai có câu trả lời dứt khoát về hành vi đúng hay không. Tiêu chuẩn này dường như tuyên bố rằng không có hàm nào được khởi tạo, nhưng ba trình biên dịch phổ biến khởi tạo trong một số trường hợp, nhưng khác nhau với nhau.

+0

Tôi hoàn toàn không đồng ý, theo như tôi thấy Tiêu chuẩn yêu cầu chức năng được khởi tạo khi địa chỉ của nó được chụp và tất cả 6 địa chỉ được thực hiện. Nếu không thể khởi tạo hàm (1, 3 và 4) thì lỗi biên dịch sẽ được nâng lên. Vì vậy, tôi sẽ nói rằng 2, 5 và 6 nên được khởi tạo; và kể từ khi địa chỉ của họ được thực hiện (cho dù bạn cast để 'void' là không thích hợp) sự vắng mặt của họ nên kích hoạt một lỗi linker (trừ khi tối ưu hóa). –

+0

'theo như tôi thấy' - ở đâu? Phần và đoạn, xin vui lòng. Các phôi để vô hiệu hóa chỉ đơn giản là để tránh cảnh báo về các biểu thức được sử dụng như báo cáo, không liên quan đến những gì tôi đang làm. – Fuz

+0

Nếu tôi có phần và đoạn, nó sẽ là một câu trả lời;) Tôi tin rằng nó nằm trong trường hợp được sử dụng. –

Trả lời

6

Một định nghĩa hàm cần thiết nếu bạn lấy địa chỉ của nó (trong ngữ cảnh được đánh giá).

Tất nhiên định nghĩa có thể được đưa ra trong một đơn vị dịch thuật riêng biệt, nhưng điều đó không thay đổi thực tế là một định nghĩa là cần thiết.

Nếu chỉ có một hàm thành viên là cần thiết, điều đó không hàm ý rằng các hàm thành viên khác cũng được khởi tạo.

Nếu mẫu chức năng không xác định, nó không thể được khởi tạo ngầm. Sau đó nó phải được khởi tạo rõ ràng trong một đơn vị dịch thuật khác. Dựa vào sự khởi tạo ngầm trong một đơn vị dịch khác không được phép (nhưng không yêu cầu chẩn đoán).

+0

14p6 cho điểm cuối cùng đó, tôi nghĩ vậy. Về điểm chính của bạn, một định nghĩa hàm không cần thiết để có thể nhìn thấy ngay cả khi nó được * gọi là *, nhưng tiêu chuẩn rõ ràng dự định rằng một kết quả cuộc gọi trong instantiating một định nghĩa mẫu chức năng; lấy một con trỏ không khác gì. – ecatmur

+0

14.7.1/2 nói "chuyên môn mẫu chức năng được khởi tạo ngầm khi chuyên môn được tham chiếu trong ngữ cảnh yêu cầu định nghĩa hàm tồn tại". Đó là một chút len ​​(trong tâm trí của tôi), nhưng tôi đoán điều này có thể được giải thích theo cách đó. Nếu vậy, có phải Clang thiếu bằng cách không khởi tạo các mẫu chức năng không phải là thành viên không? Tôi ít ngạc nhiên bởi VC làm cho nó sai. :) – Fuz

+0

Tôi đã đánh dấu đây là câu trả lời được chấp nhận, mặc dù tôi sẽ hạnh phúc hơn nếu có giải thích rõ ràng hơn 'yêu cầu định nghĩa hàm tồn tại' để xem hành vi của VC và Clang có bị xử phạt theo tiêu chuẩn hay không. – Fuz

0

Cần phải xảy ra sự kiện hóa vì việc mở rộng mẫu có thể không dẫn đến mã được định dạng tốt.

Trên thực tế, sự kiện có thể thậm chí không dẫn đến mẫu thử hợp lệ (lỗi này sẽ đủ điều kiện là 'không phải là lỗi').

(Khi SFINAE có liên quan đến địa chỉ hiệu quả được thực hiện có thể bỏ qua nhiều trước các ứng cử viên trong thứ tự từng phần (vì Thay Failure không phải là một Lỗi), trước khi ứng cử viên thực sự được lựa chọn để lấy địa chỉ của.)

+0

Tôi nghĩ rằng điều này là không chính xác. 14.7.1/8 nói "Nếu một mẫu chức năng hoặc chuyên môn về mẫu chức năng thành viên được sử dụng theo cách liên quan đến độ phân giải quá tải, thì việc khai báo chuyên môn được ngầm hóa rõ ràng". Lưu ý * khai báo * được khởi tạo, không phải định nghĩa. – Fuz

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