In range-based for loop index bekommen
-
Das ich jetzt eigenen Code zeige, heißt nur, das ich im Moment zu faul, bin ein Beispiel zu schreiben.
Hier funktioniert es nicht. Kann aber sein, das ich ein Verständnisfehler habe
for ( const auto& charset : cycling_charset ) { auto i = &charset - cycling_charset; paintModularPattern( paint, pattern, 0, 0, cycling_charset[ i ] ); //paintModularPattern( paint, pattern, 0, 0, charset ); //ursprünglich console.writeBuffer(); std::cout << i; key(); }
Mein Fehler kann auch sein, das
values
unklar ausgedrückt ist. Wollte eigentlich durchconst auto&
dies klarer machen, habe aber unsauber vorgearbeitet.
-
Welchen Typ hat denn
cycling_charset
? Und was bedeutet "funktioniert nicht"?Ich würde die auskommentierte, "ursprünglich"-Zeile weiter verwenden. Wenn die schon nicht funktioniert,
dann ist dein Problem nicht dadurch zu lösen, dass du via Index auf die Datenstruktur zugreifst.Überlege auch, ob du das
i
überhaupt benötigst. Wenn dasstd::cout << i
nur eine Debug-Ausgabe sein soll,
dann sehr wahrscheinlich nicht.
-
Finnegan schrieb:
Swordfish schrieb:
Bei einem
T[]
,std::array<T>
oderstd::vector<T>
tut es. Egal wasT
ist.Es ging mir nicht um das
T
sondern eben um die von dir genannten Datenstrukturen.Das ist mir schon klar. Du hast es auch mit
Finnegan schrieb:
[...] man nagelt sich damit unnötig auf Datenstrukturen fest, bei der die Elemente direkt hintereinander im Speicher liegen.
deutlich gesagt. Das quote Deiner Aussage war übrigens als Antwort auf
lemon03 schrieb:
Das Beispiel von Swordfish funktioniert auch nur mit ints und ähnlichen? Bei Objekten zB nicht mehr.
gedacht.
-
cycling_charset
ist einvector
auscharset
.Aber nein, funktioniert alles. Ich wollte nur mal schnell "im laufenden Betrieb" nachschauen, an welcher Stelle ein bestimmter charset steht und die Stelle, das
i
, ausgeben lassen.Dabei bin ich, wie schon vorher ein paar Mal, auf diese Frage gestoßen. Und habe mich aufgerafft mal nachzufragen.Die obige Funktion mit ausgegebenen index existiert nur in diesem Moment und in diesem Forum.
Wegen nicht funktioniert:
error: no match for 'operator-' (operand types are 'const Charset*' and 'std::vector<Charset>')
-
lemon03 schrieb:
Wegen nicht funktioniert:
error: no match for 'operator-' (operand types are 'const Charset*' and 'std::vector<Charset>')
#include <vector> #include <iostream> struct charset { charset(int foo) : foo{ foo } {}; int foo; }; int main() { std::vector<charset> cycling_charset{ 1, 2, 3 }; for (const auto& charset : cycling_charset) { auto i = &charset - &cycling_charset[0]; std::cout << i << '\n'; } }
-
wieder kein
match
, aber etwas ausgeführterauto i = &charset - cycling_charset[ 0 ];
|error: no match for 'operator-' (operand types are 'const Charset*' and '__gnu_cxx::__alloc_traits<std::allocator<Charset> >::value_type {aka Charset}')|
Aber liebe Leute
Wenn es kein höheren Grund, wie zB aus Erkenntnis-Gründen gibt, reicht mir das Mitzählen vollkommen aus. Ich brauchte diesen index genau einmal und hatte ihn.
-
lemon03 schrieb:
wieder kein
match
, aber etwas ausgeführterauto i = &charset - cycling_charset[ 0 ];
|error: no match for 'operator-' (operand types are 'const Charset*' and '__gnu_cxx::__alloc_traits<std::allocator<Charset> >::value_type {aka Charset}')|
Mensch, Du hast den Adressoperator vor
cycling_charset[0]
übersehen.
-
Achhaje!
Na dann danke ich recht herzlich
-
Es sei angemerkt, dass man sich ein "range-based for mit Index" per Makro bauen kann, du kannst dann sowas schreiben:
`foreach_i(v,values)std::cout << i << ": " << v << std::endl;
foreach_i(v,values)v=i;`
Bzw. FOREACH_I, um sich an Konventionen zu halten. Ein äquivalentes FOREACH_J bietet sich dann auch noch an.
-
;sergey schrieb:
Es sei angemerkt, dass man sich ein "range-based for mit Index" per Makro bauen kann, du kannst dann sowas schreiben:
`foreach_i(v,values)std::cout << i << ": " << v << std::endl;
foreach_i(v,values)v=i;`
Klar geht das.
Mir fällt jetzt aber z.B. nix ein wie man das mit range based for umsetzen könnte. Und wenn man range based for emulieren muss, dann kommt wieder so ein Monster wie
BOOST_FOREACH
raus.Hab ich da was übersehen, also geht das auch irgendwie einfach & elegant?
-
hustbaer schrieb:
Hab ich da was übersehen, also geht das auch irgendwie einfach & elegant?
Kommt drauf an, was man unter einfach und elegant versteht. Statt Macros zu verwenden würde ich std::for_each erweitern:
#include <iostream> #include <vector> template<class InputIt, class Function> Function for_each(InputIt first, InputIt last, Function f) { for (int idx = 0; first != last; ++first, ++idx) { f(*first, idx); } return f; } int main() { std::vector<int> v = { 1, 2, 3, 4 }; for_each( v.begin(), v.end(), []( auto& val, int idx ) { std::cerr << idx << " = " << val << "\n"; }); }
-
hustbaer schrieb:
Mir fällt jetzt aber z.B. nix ein wie man das mit range based for umsetzen könnte. Und wenn man range based for emulieren muss, dann kommt wieder so ein Monster wie
BOOST_FOREACH
raus.Hab ich da was übersehen, also geht das auch irgendwie einfach & elegant?
Können wir ja mal drüber reden, denn mir gefällt die Lösung, die ich vor Jahren mal geschrieben habe, nicht wirklich.
#define FOREACH_I(NAME,RANGE) for (size_t i=size_t(-1),_fe_continue=true;_fe_continue;_fe_continue=false) for (auto&& NAME : RANGE) if (true | ++i)
An der Lösung ist besonders problematisch, dass der IDE die Definition des Makro natürlich bekannt ist und daher den Block nach dem foreach_i automatisch einrückt:
FOREACH_I(v,values) { }
Andere Ideen ohne dieses Problem sind willkommen (alle Features bis C++17 erlaubt).
-
hustbaer schrieb:
Hab ich da was übersehen, also geht das auch irgendwie einfach & elegant?
Hatten wir das nicht schon? https://www.c-plusplus.net/forum/p2552252#2552252
-
@manni66 & Arcoth
Ich hab ganz bewusst den Beitrag von ;sergey zitiert wo er eine Makro-Lösung erwähnt die sich so wie von ihm gezeigt aufrufen lässt.Dass es grundsätzlich auch anders als mit Makro geht ist schon klar.
-
;sergey schrieb:
#define FOREACH_I(NAME,RANGE) for (size_t i=size_t(-1),_fe_continue=true;_fe_continue;_fe_continue=false) for (auto&& NAME : RANGE) if (true | ++i)
Du solltest den Loop-Body auf jeden Fall in den else Zweig verschieben. Sonst gibt's Probleme bei sowas wie
if (foo) FOREACH_I(v, values) v += i; else bar();
Also statt
if (true | ++i)
lieber sowas wieif (++i, false) {} else
Und genau das, also der "if Trick", ist das an was ich nicht gedacht hatte.
;sergey schrieb:
An der Lösung ist besonders problematisch, dass der IDE die Definition des Makro natürlich bekannt ist und daher den Block nach dem foreach_i automatisch einrückt:
FOREACH_I(v,values) { }
Meine IDE ist für sowas zu doof, die rückt das nur 1x ein