2011-05-23 49 views
10

Nói rằng tôi có một đối tượng của một số lớp container STL obj. Tôi có thể xác định đối tượng khác cùng loại theo cách này:Hành vi của decltype

decltype(obj) obj2; 

Nhưng tôi không thể tuyên bố iterator cho container theo cách này:

decltype(obj)::iterator it = obj.begin(); 

Tại sao? Tôi có làm điều gì sai?

Trả lời

15

Mã của bạn là tốt được hình thành theo quy định của dự thảo C++ 0x thức (FDI) . Đây là một sự thay đổi muộn mà chưa được thực hiện bởi trình biên dịch Visual Studio.

Trong khi đó, một cách giải quyết là sử dụng một typedef:

typedef decltype(obj) obj_type; 
obj_type::iterator it = obj.begin(); 

EDIT: Chương có liên quan và câu là 5.1.1/8:

 
qualified-id: 
    [...] 
    nested-name-specifier templateoptunqualified-id 

nested-name-specifier: 
    [...] 
    decltype-specifier :: 

decltype-specifier: 
    decltype (expression) 

Và vì lợi ích đầy đủ của :

The original core issue

Proposal for wording

+0

Cảm ơn bạn @ JohannesD.Nếu bạn chỉnh sửa câu trả lời của bạn, hãy thêm số đoạn của bản nháp cuối cùng cho biết điều này tôi sẽ chấp nhận câu trả lời của bạn. –

+0

@Mihran - Ở đây bạn đi :) – JohannesD

7

Đó là vì cách mà ngôn ngữ được phân tách.

decltype(obj)::iterator it = obj.begin(); 

Bạn muốn nó trở thành

(decltype(obj)::iterator) it; 

Nhưng trong thực tế, nó trở nên

decltype(obj) (::iterator) it; 

Tôi phải thừa nhận, tôi cũng rất ngạc nhiên khi thấy rằng đây là trường hợp, như tôi chắc chắn rằng tôi đã làm điều này trước đây. Tuy nhiên, trong trường hợp này, bạn có thể chỉ cần sử dụng auto, hoặc thậm chí decltype(obj.begin()), nhưng ngoài ra, bạn có thể làm

typedef decltype(obj) objtype; 
objtype::iterator it; 
+0

Cảm ơn bạn cho 'auto'. Nhưng typedefing không phải là ý kiến ​​hay trong quan điểm của tôi. Tôi đang làm điều này để tránh typedefing. –

+0

@Mihran Hovsepyan: Tại sao? Mã của bạn là tùy thuộc vào một tiêu chuẩn 'typedef'-nó hầu như không' typedef'-miễn phí. 'typedef' khó tránh khỏi trong C++ khi nó đứng. – Puppy

+0

sự phân lớp của tôi là trong tiêu đề, nhưng các phương pháp trong cpp, vì vậy mỗi lần trong quá trình thực hiện cpp tôi nên mở tiêu đề và xem loại của một thành viên là gì. Nhưng như mọi lập trình viên tôi đang cố gắng để được lười biếng)) –

2

Tuy nhiên, một workaround cho đến khi phân tích cú pháp VC++ 's là cố định để phản ánh các doanh nghiệp FDI là sử dụng std::identity<> metafunction:

std::identity<decltype(obj)>::type::iterator it = obj.begin(); 
+1

FWIW, 'std :: identity' đã bị xóa, do đó, điều đó phụ thuộc hiệu quả vào VC2010. (Đơn giản là đủ để viết nó.) – GManNickG

+0

@GMan: Phải, tôi chỉ đề cập đến nó bởi vì câu hỏi của OP là VC++ 2010 cụ thể. : -] – ildjarn