std::get<i> bei std::tuple



  • Ich möchte auf ein tuple element zur Laufzeit zugreifen. Geht das?

    Wenn ich in einer for schleife mit einem iterator zugreife

    std::tuple<int,int,int> blub = std::make_tuple( 10 , 20 , 30 );
    
    for( int i = 0 ; i < 3 ; i++ )
    {
       std::cout << std::get<i>( blub ) << std::endl;
    }
    

    Bekomme ich zur Kompilierzeit einen Fehler, der mich darauf hinweist, dass i zur Kompilierzeit bekannt sein muss. Kann ich so etwas mit tuple umgehen?



  • Dafür gibt es tuple::tie



  • ich 2 schrieb:

    Ich möchte auf ein tuple element zur Laufzeit zugreifen. Geht das?

    Nicht direkt, der Ausdruck muss ja einen Typen haben. Typen stehen zur Kompilierzeit fest.

    Du könntest etwas mit Boost.Fusion versuchen, allerdings wäre es sinnvoller, wenn du uns sagst, was du vorhast.

    <💡>



  • glühbirne schrieb:

    allerdings wäre es sinnvoller, wenn du uns sagst, was du vorhast.

    Ich habe die wahl zwischen diesem hässlichen code

    std::vector<std::tr1::array<unsigned char,3>> colors;
    colors.resize( 8 );
    colors[0][0] =   0 ; colors[0][1] =  0  ; colors[0][2] =   0;
    colors[1][0] = 255 ; colors[1][1] =  0  ; colors[1][2] =   0;
    colors[2][0] =   0 ; colors[2][1] = 255 ; colors[2][2] =   0;
    colors[3][0] =   0 ; colors[3][1] =   0 ; colors[3][2] = 255;
    colors[4][0] = 255 ; colors[4][1] = 255 ; colors[4][2] =   0;
    colors[5][0] =   0 ; colors[5][1] = 255 ; colors[5][2] = 255;
    colors[6][0] = 255 ; colors[6][1] =   0 ; colors[6][2] = 255;
    colors[7][0] = 255 ; colors[7][1] = 255 ; colors[7][2] = 255;
    

    oder diesem schöneren code

    std::vector<std::tuple<unsigned char,unsigned char,unsigned char>> colors;
    
    colors.push_back( std::make_tuple(   0 ,  0 ,    0 ) );
    colors.push_back( std::make_tuple( 255 ,  0 ,    0 ) );
    colors.push_back( std::make_tuple(   0 , 255 ,   0 ) );
    colors.push_back( std::make_tuple(   0 ,   0 , 255 ) );
    colors.push_back( std::make_tuple( 255 , 255 ,   0 ) );
    colors.push_back( std::make_tuple(   0 , 255 , 255 ) );
    colors.push_back( std::make_tuple( 255 ,   0 , 255 ) );
    colors.push_back( std::make_tuple( 255 , 255 , 255 ) );
    

    Später geht es einfach um den Zugriff... und ich wollte dafür nicht unebedingt einen neuen Datentyp anlegen.



  • sind alle 2 schrott.

    mach einen
    vector<color>

    und schreib dir eine color Klasse.

    PS:
    color kann zB auch ein int sein 😉



  • Shade Of Mine schrieb:

    sind alle 2 schrott.

    mach einen
    vector<color>

    und schreib dir eine color Klasse.

    PS:
    color kann zB auch ein int sein 😉

    Selber schreiben lohnt sich nicht immer, ich habe sonst eine wxWidgets Klasse wxColour. Da sind dann auch alle anderen Farboperationen/Konversionen drin die man sonst so braucht. Sie speichert allerdings m_red,m_green,m_blue. D.h. ich kann nicht schön durch die Kanäle iterieren..



  • Eigentlich wäre ja std::array eher der Typ den du suchst, bin ich der Meinung. Aber die kann man auch erst mit C++11 schön initialisieren... Ansonsten müsste man sich da selber was basteln und dann könnte man sich auch gleich fix eine Farbklasse mit Array drin machen...



  • Decimad schrieb:

    Eigentlich wäre ja std::array eher der Typ den du suchst, bin ich der Meinung. Aber die kann man auch erst mit C++11 schön initialisieren... Ansonsten müsste man sich da selber was basteln und dann könnte man sich auch gleich fix eine Farbklasse mit Array drin machen...

    Eine Farbklasse lohnt es sich nicht wirklich selber zu implementieren. Der üblicherweise gebrauchte Funktionumfang ist nicht ohne weiteres zu bewältigen. Daher nehme ich sonst für Farben wxWidgets.

    Wenn es nur um die drei Arrayelemente geht dann tuts auch ein array .



  • Na so meinte ich das nicht.
    std::array ist schon das, was eher auf dein Problem passt als std::tuple.
    Aber wenn Dein compiler std::array noch nicht elegant hergibt, dann schreibt man sich halt schnell einen RGB-Array wrapper, keine ausgewachsene Farb-Klasse.



  • ungetestet

    std::array<unsigned char, 3> make_color(unsigned char r, unsigned char g, unsigned char, b){
        std::array<unsigned char, 3> color;
        color[0]=r;
        color[1]=g;
        color[2]=b;
        return color;
    }
    
    std::vector<std::array<unsigned char,3>> colors;
    colors.push_back( make_color(   0 ,  0 ,    0 ) );
    ...
    


  • otze, du kannst std::array auch ohne C++11 Initializer List Support direkt füllen:

    std::array<unsigned char, 3> color = {r, g, b};
    

    Eventuell könnte man mit gut unterstütztem C++11 sogar direkt

    colors.push_back({r, g, b});
    

    schreiben. Bin mir hier allerdings nicht sicher, da std::array ein Aggregat ist und keine Konstruktoren hat.

    Jedenfalls ist mit leichtem C++11 auch das möglich:

    struct rgb
    {
        explicit rgb(unsigned char r, unsigned char g, unsigned char b);
        std::array<unsigned char, 3> values;
    };
    
    std::vector<rgb> colors;
    colors.emplace_back(r, g, b);
    

Anmelden zum Antworten