Можно ли объявить две переменные разных типов в цикле for?

можно ли объявить две переменные разных типов в организме инициализации цикла for В C++?

например:

for(int i=0,j=0 ...

определяет два целых числа. Могу ли я определить int и char в теле инициализации? Как это сделать?

6 ответов


невозможно, но вы можете сделать:

float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
  //...
}

или явно ограничить область f и i использовать дополнительные скобки:

{
    float f; 
    int i;
    for (i = 0,f = 0.0; i < 5; i++)
    {
       //...
    }
}

нет-но технически есть обходной путь (не то, чтобы я действительно использовал его, если не вынужден):

for(struct { int a; char b; } s = { 0, 'a' } ; s.a < 5 ; ++s.a) 
{
    std::cout << s.a << " " << s.b << std::endl;
}

C++17: вы должны использовать структурированная обязательная декларация. Синтаксис поддерживается в gcc-7 и clang-4.0 ( clang живой пример). Это позволяет нам распаковать кортеж следующим образом:

for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"abc"}}; i < N; ++i) {
    // ...
}

C++14: вы можете сделать то же самое, что и C++11 (ниже) с добавлением типа std::get. Так вместо std::get<0>(t) в приведенном ниже примере, вы можете иметь std::get<int>(t).


C++11: std::make_pair позволяет сделать это, а также std::make_tuple для более чем двух объектов.

for (auto p = std::make_pair(5, std::string("Hello World")); p.first < 10; ++p.first) {
    std::cout << p.second << std::endl;
}

std::make_pair вернет два аргумента в std::pair. К элементам можно получить доступ с помощью .first и .second.

для более чем двух объектов, вы должны использовать std::tuple

for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
        std::get<0>(t) < 10;
        ++std::get<0>(t)) {
    std::cout << std::get<1>(t) << std::endl; // cout Hello world
    std::get<2>(t).push_back(std::get<0>(t)); // add counter value to the vector
}

std::make_tuple - это вариационный шаблон, который построит кортеж из любого количества аргументов (с некоторыми техническими ограничениями, конечно). К элементам можно получить доступ по индексу с помощью std::get<INDEX>(tuple_object)

внутри контура тела вы можете легко псевдоним объекты, хотя вы все равно должны использовать .first или std::get для условия цикла for и выражения обновления

for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
        std::get<0>(t) < 10;
        ++std::get<0>(t)) {
    auto& i = std::get<0>(t);
    auto& s = std::get<1>(t);
    auto& v = std::get<2>(t);
    std::cout << s << std::endl; // cout Hello world
    v.push_back(i); // add counter value to the vector
}

C++98 и C++03 вы можете явно назвать типы std::pair. Нет стандартного способа обобщить это более чем на два типа:

for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
    std::cout << p.second << std::endl;
}

вы не можете объявить несколько типов в инициализации, но вы можете назначить нескольким типам E. G.

{
   int i;
   char x;
   for(i = 0, x = 'p'; ...){
      ...
   }
}

просто объявите их в своей собственной области.


в разделе "есть ли способ определить переменные двух типов в цикле for? " для другого способа, включающего вложенность нескольких для циклов. Преимущество в другую сторону за "структура трюк Георга" заключается в том, что он (1) позволяет иметь сочетание статических и нестатических локальных переменных и (2) это позволяет иметь некопируемых переменных. Недостатком является то, что он гораздо менее читаем и может быть менее эффективным.


определить макрос:

#define FOR( typeX,x,valueX,  typeY,y,valueY,  condition, increments) typeX x; typeY y; for(x=valueX,y=valueY;condition;increments)

FOR(int,i,0,  int,f,0.0,  i < 5, i++)
{
  //...
}

просто помните, что ваши области переменных также не будут находиться в цикле for.