2014-10-17 16 views
15

Các bit mã sau biên dịch trong VS2008 và GCC 4.8.2typedef Foo <> Biên dịch Foo nhưng nó có hợp lệ không?

template<typename T=void> 
struct Foo 
{ 
}; 

// typedef Foo<> Foo; // Does *NOT* compile 

int main() 
{ 
    typedef Foo<> Foo; 
    Foo f1; 

    // Foo<char> f2;  // Does *NOT* compile 
    //::Foo<char> f3; // COMPILES 
} 

Có hợp lệ?

+1

Bạn đang cung cấp đối số mặc định trong mẫu. Nó hoàn toàn hợp lệ. –

+2

@Captain: Nhưng thực tế là cả hai đều có tên là 'Foo'? – Cameron

Trả lời

17

Theo C++ 11 3.3.10/1:

Một tên có thể được ẩn bởi một tuyên bố rõ ràng về điều đó cùng tên trong a khu vực khai báo lồng nhau hoặc có nguồn gốc lớp.

(tôi nhấn mạnh)

Đó là lý do tại sao các mẫu tên Foo có thể được ẩn bằng tên typedef Foo bên main() (một phạm vi khác nhau), nhưng không phải trong phạm vi giống như tên mẫu được công bố.

Là tại sao trường hợp tương tự này là hợp pháp:

struct Foo 
{ 
}; 

typedef Foo Foo; // *DOES* compile 

Đó được cho phép một cách rõ ràng bởi 7.1.3/3:

Trong một phạm vi không lớp nào đó, một specifier typedef có thể được sử dụng để xác định lại tên của bất kỳ loại nào được khai báo trong phạm vi đó để chỉ loại mà nó đã đề cập đến.

+4

+1 để trích dẫn thông số kỹ thuật! –

+1

3.3.1 [basic.scope.declarative]/p4 cũng có liên quan. –

11

Vâng đó là hợp lệ, với cùng lý do rằng đây là hợp lệ:

struct Foo { }; 

namespace bar { 
    struct Foo { }; 
} 

Bạn chỉ cần ghi đè lên tên trong một phạm vi khác nhau. Bên trong chính, bạn vẫn có thể làm điều gì đó như:

::Foo<int> f2; 
+0

Ah, đánh bóng tên tệp. Làm thế nào ngon lén lút: O – Cameron

+0

Tôi nghĩ rằng câu trả lời này là không đúng - có một mẫu Foo thay thế bằng typedef (trong một không gian tên) –

+0

@ DieterLücking Tại sao? Tôi có thể dễ dàng tạo ra một 'int Foo = 7; 'Nó chỉ là một cái tên. – Barry

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