Заменить ключевое слово auto с выведенным типом (clang или VS2010)

Кто-нибудь написал script, плагин или исполняемый файл, который заменяет каждый экземпляр "auto" на тип, основанный на компиляторе? Мне нужно перенести некоторый код С++ 11, который автоматически использует все места.

Клэнг - мой первый кандидат. Кто-нибудь изменил его, чтобы сделать что-то вроде этого?

Альтернативой является анализ ошибок компилятора, поскольку ожидаемый тип может быть в выводе ошибки. Я мог бы -Dauto=int и, возможно, вернуться "could not convert std::vector<int>::iterator to 'int'"

Ответ 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 при инициализации