iterator casten



  • moin,

    ich möchte einem algorithmus gerne ein iteratoren-paar übergeben, das auf chars verweist, jedoch möchte ich dem algorithmus vorgaukeln, dass er es mit ints zu tun hat (hat mit der implementierung des algorithmus zu tun). gibt es so etwas wie einen casted iterator oder muss man sich das selbst zusammenbasteln?

    lglg


  • Mod

    Mehr Kontext. Und genauere Beschreibung, was für ein Verhalten erzeugt werden soll. Und Beschreibung, wieso es nicht reicht, dem Algorithmus zu sagen, ints zu benutzen und ihm einfach trotzdem einen char-Iterator zu übergeben; chars sind schließlich implizit in int umwandelbar.

    PS: Und nein, so etwas gibt es nicht vorgefertigt. Denn wie oben erklärt, ist es wahrscheinlich gar nicht nötig.



  • ich hab chars als iterierbare datenstruktur vorliegen und möchte die einer funktion füttern, die input iteratoren akzeptiert. das gewünschte verhalten wird jedoch nur für iterator_traits<iter_t>::value_type == int (oder grösser) erzielt.
    demonstration, wieso es eine rolle spielt:

    #include <iostream>
    #include <vector>
    
    template<typename iter_t>
    void foo(iter_t first, iter_t last)
    {
    	for(; first != last; ++first)
    	{
    		(*first) *= 119;
    		(*first) %= 100;
    	}
    }
    
    int main()
    {
    	std::vector<char> vec_char = {1, 2, 3, 4, 5};
    	std::vector<int> vec_int(vec_char.begin(), vec_char.end());
    
    	foo(vec_char.begin(), vec_char.end());
    	for(int i : vec_char)
    	{
    		std::cout << i << ' ';
    	}
    	std::cout << '\n';
    
    	foo(vec_int.begin(), vec_int.end());
    	for(auto&& i : vec_int)
    	{
    		std::cout << i << ' ';
    	}
    }
    
    19 -18 1 -36 83 
    19 38 57 76 95
    

    http://ideone.com/OGXzL4

    da die funktion nur input iteratoren verlangt, dachte ich, lässt sich relativ einfach ein iterator wrapper schreiben, der das aktuelle element gecastet speichert und beim advancen des iterators dann zurückcastet. wollte nur wissen, ob das schon in irgendeiner art vorliegt.


  • Mod

    Nein, das gibt es nicht fertig. In diesem Fall würde es auch überhaupt nichts bringen, da der unterliegende Datentyp immer noch char ist und in einen char passt nun einmal kein int, wenn man ihn zwischenspeichert. Jedoch würde ich sagen, ist hier die Implementierung der Funktion kaputt. So geht's unabhängig vom Datentyp:

    (*first) = *first * 119 % 100;
    

    Ist mir schon klar, dass das nur ein Beispiel ist, aber es soll dir verdeutlichen, dass es wahrscheinlich eine Schwäche in der Implementierung der Funktion ist. Wenn gewünscht wird, dass die Funktion in einem Wertebereich arbeitet, der die Zwischenergebnisse aufnehmen kann, dann darf man eben nicht in einem kleineren Typen zwischenspeichern. Das wäre dann eben schlicht falsch, weil die Funktion nicht das gewünschte Ergebnis erzielt. Wenn es unbedingt in mehreren Schritten sein muss:

    auto temp  = *first * 119;
          *first = temp % 100;
    

    PS: deine Funktion braucht übrigens mindestens einen Forward-Iterator, da du den dereferenzierten Wert sowohl als einen r- als auch als l-value benutzt und du erwartest, dass die Dereferenzierung multipass ist.



  • Man könnte mit einem transform_iterator einen Iterator erzeugen, der Proxy-Objekte zurückgibt, die sich so ein bisschen wie ints verhalten:

    class int_for_char_proxy
    {
    public:
        explicit int_for_char_proxy(char& c): c(c) {}
    
        opeartor int() const { return c; }
        int_for_char_proxy& operator=(int i) const { c = i; return *this; }
        int_for_char_proxy& operator+=(int i) const { c += i; return *this; }
        int_for_char_proxy& operator-=(int i) const { c -= i; return *this; }
        int_for_char_proxy& operator*=(int i) const { c *= i; return *this; }
        int_for_char_proxy& operator%=(int i) const { c %= i; return *this; }
        int_for_char_proxy& operator/=(int i) const { c /= i; return *this; }
    
    private:
        char& c;
    };
    

    (oder so ähnlich, ich hab's nicht getestet)

    Aber ob es wirklich das ist, was du tun solltest, weiß ich nicht.

    Und ja, SeppJ hat da völlig Recht. Mit einem "InputIterator" gibt sich dein Funktionstemplate nicht zufrieden. Das, was ein InputIterator kann, ist sehr eingeschränkt.


Log in to reply