Подтвердить что ты не робот

С++ 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

который решает эту проблему читаемости

4b9b3361

Ответ 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)

Авто не будет работать, но я все еще жду полиморфных лямбдов. Мой подход теоретически способен обрабатывать кортежи.