Ответ 1
К сожалению, это невозможно в общем случае. Рассмотрим:
template <typename T> void foo(T & t)
{
auto it = t.find(42);
...
}
...
std::map<int, int> m;
std::set<int> s;
...
foo(m);
foo(s);
По общему признанию, это бессмысленный пример, но он показывает, что нет способа узнать, что заменить auto, когда оно зависит от аргумента шаблона. std::map
и std::set
, кстати, содержат typedef с тем же именем (iterator
), которые представляют тип соответствующего итератора, поэтому typename T::iterator it
будет работать здесь, но вы можете создать экземпляр foo
для T
который не имеет такого typedef.
Многочисленные typedefs в стандартных классах библиотек были добавлены точно, чтобы позволить создавать такие шаблоны до того, как auto
был изобретен/переназначен, и вы можете сделать то же самое, чтобы иметь дело с компилятором, у которого нет auto
. Но это не то, что вы можете автоматизировать, по крайней мере, без усилий, сравнимых с добавлением поддержки auto
к компилятору...
Даже если auto
не зависит от типа шаблона, трудно заменить его чем-то, что имеет смысл для пользователя и переносится. Возьмем:
std::map<int, int> m;
auto it = m.find(42);
Разумная замена для auto
равна std::map<int, int>::iterator
, но если вы используете -Dauto=int
и посмотрите на сообщения об ошибках компилятора, вы замените его чем-то вроде std::_Rb_tree_iterator<std::pair<const int, int> >
. Эта деталь реализации стандартной библиотеки, трудночитаемая и, очевидно, не переносимая - вы не хотите этого в своем коде.
В вашем примере мой компилятор (GCC 4.4.6) говорит:
error: невозможно преобразовать
__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >
вint
при инициализации