Поведение decltype - PullRequest
11 голосов
/ 23 мая 2011

Скажем, у меня есть объект некоторых контейнерных классов stl obj. Я могу определить другой объект того же типа следующим образом:

decltype(obj) obj2;

Но я не могу объявить итератор для контейнера следующим образом:

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

Почему? Я что-то не так делаю?

Ответы [ 3 ]

16 голосов
/ 24 мая 2011

Ваш код правильно сформирован в соответствии с окончательным проектом C ++ 0x (FDIS).Это было позднее изменение, которое еще не было реализовано компилятором Visual Studio.

Тем временем, обходной путь должен использовать typedef:

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

EDIT: Соответствующая глава и стих: 5.1.1 / 8:

<i>qualified-id:</i>
    [...]
    <i>nested-name-specifier</i> template<sub>opt</sub> <i>unqualified-id</i>

<i>nested-name-specifier:</i>
    [...]
    <i>decltype-specifier</i> ::

<i>decltype-specifier:</i>
    decltype ( <i>expression</i> )

И ради полноты:

Оригинальный основной выпуск

Предложение по формулировке

8 голосов
/ 23 мая 2011

Это из-за способа синтаксического анализа языка.

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

Вы хотите, чтобы оно стало

(decltype(obj)::iterator) it;

Но на самом деле оно становится

decltype(obj) (::iterator) it;

Я должен признать, я также был удивлен, увидев, что это было так, так как я уверен, что я делал это раньше. Однако в этом случае вы можете просто использовать auto или даже decltype(obj.begin()), но, кроме того, вы можете сделать

typedef decltype(obj) objtype;
objtype::iterator it;
2 голосов
/ 24 мая 2011

Еще один обходной путь до исправления синтаксического анализатора VC ++ для отражения FDIS заключается в использовании метафункции std::identity<>:

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