Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behavior of decltype

Say I have an object of some of stl container classes obj. I can define other object of same type this way:

decltype(obj) obj2;

But I can't declare iterator for the container this way:

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

Why? Am I doing something wrong?

like image 506
Mihran Hovsepyan Avatar asked May 23 '11 19:05

Mihran Hovsepyan


3 Answers

Your code is well-formed according to the final C++0x draft (FDIS). This was a late change that's not yet been implemented by the Visual Studio compiler.

In the meantime, a workaround is to use a typedef:

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

EDIT: The relevant chapter and verse is 5.1.1/8:

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

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

decltype-specifier:
    decltype ( expression )

And for completeness's sake:

The original core issue

Proposal for wording

like image 90
JohannesD Avatar answered Nov 15 '22 16:11

JohannesD


It's because of the way that the language is parsed.

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

You want it to become

(decltype(obj)::iterator) it;

But in actual fact, it becomes

decltype(obj) (::iterator) it;

I have to admit, I was also surprised to see that this was the case, as I'm certain that I've done this before. However, in this case, you could just use auto, or even decltype(obj.begin()), but in addition, you can do

typedef decltype(obj) objtype;
objtype::iterator it;
like image 33
Puppy Avatar answered Nov 15 '22 16:11

Puppy


Yet another workaround until VC++'s parser is fixed to reflect the FDIS is to use the std::identity<> metafunction:

std::identity<decltype(obj)>::type::iterator it = obj.begin();
like image 37
ildjarn Avatar answered Nov 15 '22 18:11

ildjarn