2011-12-26 40 views
6

Cũ GCC 4.1.2 accepts và GCC mới 4.5.1 accepts, chương trình sau đây.Có hợp lệ để viết danh sách tham số của kiểu mẫu trong khai báo hàm dựng không?

Nhưng thực tế có đúng không? Tiêu chuẩn nói gì về việc khai báo một hàm tạo với tham số mẫu của kiểu như thế này?

(Tôi tìm thấy nó thú vị mà tôi không được phép do the same in the out-of-line definition.)

#include <iostream> 
template <typename T> 
struct Foo { 
    Foo<T>(); // <--- 
}; 

template <typename T> 
Foo<T>::Foo() { 
    std::cout << ":)"; 
} 

int main() { 
    Foo<int> f; 
} 

Lý do tôi hỏi là nó đã được đề xuất trong ý kiến ​​trên this answer rằng GCC có thể do lỗi ở đây.

+0

FWIW, cũng xây dựng và chạy trên GCC 4.6.1. – Mat

+3

Có lẽ do 12.1/1: "Cú pháp sử dụng ... tên lớp của nhà xây dựng ...", câu hỏi này có nghĩa là "là Foo ' tên lớp? " –

+0

@SteveJessop: ... "và, nếu có, tại sao nó không được chấp nhận trong định nghĩa?" –

Trả lời

3

tôi sẽ đặt một bản sao mail của một DR tốt Gần đây tôi đã gửi ra vào dịp Giáng sinh ở đây

là đoạn mã sau cũng được hình thành?

template<typename T> 
struct A { 
    A<T>(); 
}; 

Một số trình biên dịch mà tôi đã thử nghiệm (clang, g ++ và comeau conline) chấp nhận điều này. Trên thực tế 12.1 không cấm này (A<T> là một cái tên của lớp và không phải là một typedef-name), nhưng 8.3p1 nói

Một không đủ tiêu chuẩn-id xảy ra trong một declarator-id sẽ là nhận dạng đơn giản trừ cho việc kê khai của một số chức năng đặc biệt (12.3, 12,4, 13,5) ...

một constructor là một hàm thành viên đặc biệt, nhưng danh sách các tài liệu tham khảo chéo không bao gồm 12.1. Điều đó có nghĩa là mã trên bị hình thành không? Hay đây là một sự thiếu sót ngẫu nhiên?

Nếu bạn làm như vậy trong định nghĩa ngoài dòng, bạn sẽ cố gắng chuyển đối số mẫu cho hàm tạo. Đây là mã hợp lệ

struct A { 
    template<typename T> A(); 
}; 

template<> A::A<int>() { } 

Các spec nói rằng khi tên lớp tiêm được sử dụng trong một tên có trình độ khi nhìn vào phạm vi của lớp (giống như trong A::A), sau đó khi tra cứu tên chấp nhận chức năng/tên constructor , tham chiếu tên lớp được tiêm sẽ được dịch thành giải quyết cho (các) hàm khởi tạo của lớp đó (nếu ngữ cảnh tra cứu tên chỉ chấp nhận các kiểu, thì tên sẽ vẫn là tên lớp được tiêm và sẽ biểu thị loại lớp). Sau A::A, tra cứu tên hoàn tất và mang lại hàm tạo. Sau đó, <int> chỉ có thể được phân tích cú pháp dưới dạng danh sách đối số mẫu. Nếu không có mẫu trong số các nhà xây dựng của bạn, mã của bạn sẽ không hợp lệ.

+0

Đoạn đầu tiên có vẻ ngụ ý rằng mã đã cho là hợp lệ. Nhưng errr ... OP hỏi về một nhà xây dựng thường xuyên của một lớp mẫu, không phải về một constructor được tạo khuôn mẫu. ('A :: A()' i.s.o. 'A :: A ()'). – xtofl

+0

@xtofl Tôi nghĩ bạn hiểu sai câu trả lời của tôi. Sau khi bản sao của thư của tôi, tôi đã giải thích một phần câu hỏi của OP "(Tôi thấy điều thú vị là tôi không được phép làm điều tương tự trong định nghĩa ngoài dòng.)". Đoạn đầu tiên (báo giá đại diện cho thư của tôi) có nghĩa là mã được chấp nhận bởi GCC, clang và trình biên dịch trực tuyến comeau. Nó không ngụ ý rằng mã là hợp lệ. –

+0

Tôi xin lỗi; Tôi là một người thông minh, nhưng bạn có thể tóm tắt điều này cho tôi không? –

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