С++ 11 для карт и для чтения:
Новые циклы, основанные на диапазонах, действительно улучшают читаемость и очень просты в использовании. Однако учтите следующее:
map<Foo,Bar> FooAndAssociatedBars;
for (auto& FooAndAssociatedBar : FooAndAssociatedBars) {
FooAndAssociatedBar.first.doSth();
FooAndAssociatedBar.second.doSomeOtherThing();
}
Это может быть деталь, но я считаю, что было бы более читаемо, если бы я мог сделать что-то вроде:
for ( (auto& foo, auto& bar) : FooAndAssociatedBars) {
foo.doSth();
bar.doSomeOtherThing();
}
Знаете ли вы эквивалентный синтаксис?
EDIT:
Хорошая новость: на С++ 17 есть предложение, которое ссылается на эту проблему, называемое структурированными привязками (см. 1). В С++ 17 вы должны иметь возможность написать:
tuple<T1,T2,T3> f(/*...*/) {
/*...*/
return {a,b,c};
}
auto [x,y,z] = f(); // x has type T1, y has type T2, z has type T3
который решает эту проблему читаемости
Ответы
Ответ 1
Нет такой вещи, как вы хотите. Самое близкое к объявлению переменных внутри цикла:
for (auto& FooAndAssociatedBar : FooAndAssociatedBars) {
auto& foo = FooAndAssociatedBar.first;
auto& bar = FooAndAssociatedBar.second;
// ...
}
Ответ 2
Не очень хорошая идея. Рано или поздно вам понадобится то же самое для std::tuple
, и компилятор должен иметь возможность использовать std::get<>
в tuple
автоматически. На мой взгляд, ваш подход радует вас только на данный момент, и вы найдете проблемы с этим подходом (предположим, что это реализовано именно так).
В стандартном комитете с глубоким рассмотрением разработан цикл, основанный на диапазоне. Это лучше, чем цикл foreach
на других языках, и это намного короче. Соедините его с auto&
, и все готово!
Ответ 3
И, конечно, у вас всегда есть возможность использовать лямбда.
std::map<int, const char*> m { { 4, "hello" }, { 11, "c++" } };
convenient_for_each(m, [](int a, const char* b) {
std::cout << b << a << std::endl;
});
convenient_for_each(m, [](std::pair<int, const char> p) {
std::cout << p.first << p.second << std::endl;
});
Или завернутый как макрос (не рекомендуется)
FOREACH((int a, const char* b), m, std::cout << a << b << std::endl);
FOREACH((std::pair<int, const char*> p), m, std::cout << p.first << p.second << std::endl);
(Использовать пример реализации LWS)
Авто не будет работать, но я все еще жду полиморфных лямбдов. Мой подход теоретически способен обрабатывать кортежи.