Поведение decltype
Скажем, у меня есть объект некоторых классов контейнеров stl obj
. Я могу определить другой объект такого же типа следующим образом:
decltype(obj) obj2;
Но я не могу объявить итератор для контейнера следующим образом:
decltype(obj)::iterator it = obj.begin();
Почему? Я что-то делаю неправильно?
Ответы
Ответ 1
Ваш код хорошо сформирован в соответствии с окончательным проектом С++ 0x (FDIS). Это было последнее изменение, которое еще не было реализовано компилятором Visual Studio.
В то же время обходным путем является использование typedef:
typedef decltype(obj) obj_type;
obj_type::iterator it = obj.begin();
EDIT: Соответствующая глава и стих 5.1.1/8:
qualified-id:
[...]
nested-name-specifier templateoptunqualified-id
nested-name-specifier:
[...]
decltype-specifier ::
decltype-specifier:
decltype ( expression )
И ради полноты:
Исходная основная проблема
Предложение для формулировки
Ответ 2
Это из-за того, как язык анализируется.
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;
Ответ 3
Еще одно обходное решение до тех пор, пока синтаксический анализатор VС++ не будет зафиксирован для отражения FDIS, заключается в использовании метафайла std::identity<>
:
std::identity<decltype(obj)>::type::iterator it = obj.begin();