Замените ключевое слово auto на выведенный тип (clang или VS2010) - PullRequest
12 голосов
/ 20 января 2012

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

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

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

1 Ответ

8 голосов
/ 20 января 2012

К сожалению, это невозможно в общем случае. Рассмотрим:

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

...