К сожалению, это невозможно в общем случае. Рассмотрим:
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
, кстати, содержат одноименные определения типа (iterator
), которые представляют тип соответствующего итератора, поэтому typename T::iterator it
будет работать здесь, но вы можете создать экземпляр foo
для T
который не имеет такой typedef.
Многочисленные определения типов в классах стандартной библиотеки были добавлены именно для того, чтобы такие шаблоны могли быть написаны до того, как 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) говорит:
ошибка: невозможно преобразовать __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >
в int
при инициализации