2010-03-19 25 views
8

Tại sao cho không có lỗi biên dịch sau đây ?:Không "định nghĩa lại lỗi thông số mặc định" cho chức năng thành viên của mẫu lớp?

// T.h 

template<class T> class X 
{ 
public: 
    void foo(int a = 42); 
}; 

// Main.cpp 

#include "T.h" 
#include <iostream> 

template<class T> void X<T>::foo(int a = 13) 
{ 
    std::cout << a << std::endl; 
} 

int main() 
{ 
    X<int> x; 
    x.foo(); // prints 42 
} 

Dường như dù chỉ là âm thầm bỏ qua bởi trình biên dịch. Tại sao điều này?
Điều thú vị là nếu định nghĩa mẫu lớp ở trong Main.cpp thay vì tệp tiêu đề, tôi thực sự nhận được lỗi tham số mặc định.

Bây giờ tôi biết trình biên dịch sẽ phàn nàn về điều này nếu nó chỉ là một chức năng bình thường (không phải mẫu).

Tiêu chuẩn phải nói gì về các tham số mặc định trong các hàm thành viên của mẫu lớp hoặc mẫu chức năng?

+1

g ++ * * hủy bỏ việc biên dịch có lỗi. – sth

+0

Khi bạn nói "... nếu khai báo mẫu trong ..." Tôi giả sử bạn có nghĩa là định nghĩa mẫu lớp, tức là 'mẫu lớp x {....};'. Nếu vậy thì bạn đang nói rằng việc thay thế chỉ thị bao gồm với định nghĩa lớp mẫu này tạo ra một thông điệp trình biên dịch khác nhau? Điều đó gợi ý rằng có một cái gì đó khác trong tệp tiêu đề tức là thử sao chép toàn bộ nội dung của tệp tiêu đề vào nơi chỉ thị bao gồm và có lẽ bạn sẽ không nhận được cảnh báo trình biên dịch? – Troubadour

+0

Nó có thể liên quan bằng cách nào đó với lỗi VC++ này: https://connect.microsoft.com/VisualStudio/feedback/details/496593/msdn-forum-splitting-templated-function-with-default-argument-into-declaration-definition -gives-compilation-error –

Trả lời

3

8.3.6 §6 Những lập luận mặc định trong định nghĩa hàm thành viên đó xuất hiện bên ngoài của định nghĩa lớp được bổ sung vào bộ đối số mặc định được cung cấp bởi các khai báo hàm thành viên trong lớp Định nghĩa.
[Ví dụ:

class C { 
    void f(int i = 3); 
    void g(int i, int j = 99); 
}; 
void C::f(int i = 3) // error: default argument already 
{ }     // specified in class scope 
void C::g(int i = 88, int j) // in this translation unit, 
{ }       // C::g can be called with no argument 

--end dụ]

Theo tiêu chuẩn, nó sẽ cho bạn một lỗi.

+3

@tusbar bạn chỉ trích dẫn một phần của đoạn đó. Nó nói ở đầu của nó "Ngoại trừ chức năng thành viên của các mẫu lớp, ...". –

+4

Thú vị: C++ 03 khác với C++ 98. Những gì @tusbar trích dẫn là văn bản C++ 98, trong khi C++ 03 thêm ngoại lệ cho các mẫu lớp và thêm vào đoạn "Các đối số mặc định cho một hàm thành viên của một mẫu lớp sẽ được xác định trên khai báo ban đầu của hàm thành viên trong mẫu lớp. " - tôi nghi ngờ rằng điều này có nghĩa là cấm các đối số mặc định trong các định nghĩa ngoài lớp trong trường hợp các thành viên của các mẫu lớp bằng cách nói rằng bất kỳ đối số mặc định nào sẽ được chỉ định trong lớp [thay vì bên ngoài lớp]. không rõ ràng (nó có cấm các bản sao không?). –

+1

Tôi đã xem http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html # 217 và dường như ý định là cấm tất cả các arugments mặc định ngoài lớp cho các thành viên mẫu. Ngoài ra, tôi nghĩ rằng bây giờ kể từ khi đối số mặc định out-of-class được coi là khác biệt với một trong lớp, ngay cả khi lexically giống hệt nhau, nó vi phạm "sẽ được xác định trên ràng buộc ban đầu" hạn chế. Vì vậy, điều này có ý nghĩa nếu bạn nhận được một lỗi thời gian biên dịch. "Vấn đề 3.13" John Spicer đề cập đến có thể được đọc trong tài liệu này: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1995/N0607.pdf –

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