Zajímavosti z C a C++: iterace for cyklem přes proměnné různých typů

Od Petr Zemek, 2014-05-04

Pravděpodobně víte, že u for cyklů v C (od C99) a C++ lze iterační proměnnou definovat přímo v inicializační části cyklu, tedy např. for (int i = 0; ...). Dokonce lze proměnných definovat více, např. for (int i = 0, j = 1; ...). V takovém případě ale musí mít shodný typ. Co když ale potřebujeme iterovat přes více proměnných, jejichž typ se liší? Je to možné, nebo je potřeba jednu z nich definovat před cyklem? Odpověď se dozvíte v tomto příspěvku.

O co nám jde

Dejme tomu, že potřebujeme iterovat přes proměnné typu int a double pomocí for cyklu (ať už je důvod jakýkoliv, to nás teď nezajímá). Možnost, která vás napadne, je určitě tato:

double d = 0.0;
for (int i = 0; i < 10 && d < 10.0; i++, d += 0.4) {
     // ...
}

To samozřejmě funguje. Jelikož mají ale proměnné různý typ, tak nelze napsat

// Nepřeložitelné :(.
for (int i = 0, double d = 0.0; i < 10 && d < 10.0; i++, d += 0.4) {
     // ...
}

protože to není syntakticky korektní. Takže se naskýtá následující otázka.

Jde to nějak udělat?

Ano :). Například takto:

for (struct {int i; double d;} loop = {0, 0.0}; loop.i < 10 && loop.d < 10.0; loop.i++, loop.d += 0.4) {
    // ...
}

Definujeme si anonymní strukturu, která obsahuje proměnné, přes které budeme iterovat. V cyklu pak budeme k těmto proměnných přistupovat přes proměnnou loop, kterou jsme si definovali a inicializovali v inicializační části cyklu. Kód výše funguje jak v C (od C99), tak v C++.

Poznámka na závěr

V příspěvku jsem chtěl jen ukázat, že něco takového jde. To, zda to dělat, je však věc jiná, protože podobný kód může být hůře čitelný. Takže pokud byste to chtěli použít, tak se raději dvakrát zamyslete, zda není jiná, čitelnější možnost.

Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
11 + 9 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.

Možných řešení je více. Já jsem zvolil klasickou strukturu, protože toto řešení funguje jak v C, tak v C++. Co se týče té std::tuple, tak struktura je podle mě lepší řešení, protože lze jednotlivé proměnné pojmenovat. U std::tuple je možné k přístupu k položkám použít jen index (C++11) či typ (až od C++14).