Infos über neuen C++-Standard? Thread Nr.2



  • was ist das?

    Referenzen auf Referenzen sind in C++ nicht erlaubt. Man kann also nicht sowas schreiben wie:

    int&& r = ...
    

    Das scheint auf den ersten Blick kein Problem zu sein. In Verbindung mit Templates kommt es aber häufig zu solchen Referenz-auf-Referenz-Problemen. Bei der Verwendung der STL z.B. immer, wenn du versucht einen binder zusammen mit mem_fun_ref und einer Methode die ihren Parameter per Referenz erhält zu verbinden:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <functional>
    using namespace std;
    
    // Beispiel aus Scott Meyers' Effective STL
    class Widget
    {
         public:
             int readStream(istream& is)
             {
                 //...
                 return 0;
             }
    };
    int main()
    {
        vector<Widget*> vw;
        //...
        for_each(vw.begin(), vw.end(), bind2nd(mem_fun(&Widget::readStream), cin));
    }
    

    Ein einfaches Beispiel ist das:

    template <class T>
    void apply(T& arg, void (*Func)(T))
    {
        Func(arg);
    }
    
    void FuncOk(int arg)
    {}
    
    void FuncKaputt(int& arg)
    {}
    
    int main()
    {
        int x = 32;
    
        // Ok. T ist int
        apply(x, &FuncOk);
    
        // Nicht ok. T ist int&
        // Dann wäre arg aber int&& -> Referenz auf Referenz
        apply(x, &FuncKaputt);
    }
    

    Mittlerweile gibt es einen technical corrigendum der den oberen Code erlauben würde. Hier wird dann für eine Substitution von T& mit T = int& einfach zu int&. Für const gibt es sowas schon lange.



  • könnt man das nicht so machen:

    template<class T>
    struct gettype<T&> {
      typedef T type;
    };
    template<class T>
    struct gettype {
      typedef T& type;
    };
    

    [ Dieser Beitrag wurde am 26.01.2003 um 12:38 Uhr von Lars editiert. ]



  • könnt man das nicht so machen:

    Nein. So nicht. Wenn du das Base-Template noch vor die Spezialisierung schreibst, dann haut's hin 🙂
    Das ist aber nicht der Punkt. Workarounds gibt's schon lange (schau mal auf boost.org in die type_traits).

    Hier liegt aber eine Inkonsistenz vor (wie gesagt, ein const wird einfach ignoriert) und immer diese Workarounds schreiben zu müssen kann wohl auch nicht der Weißheits letzter Schluss sein.

    Aber jetzt wo ich weiß, dass es bereits ein technical corrigendum gibt, spielt das Thema für den nächsten Standard sowieso keine Rolle mehr.

    Also heute noch drum rum arbeiten und morgen (eher 2008) die neue Substitutionsregel begüßen 🙂



  • Du hast recht. SChreib das doch mal in comp.std.c++.
    Ich hab dort folgendes geschrieben:

    In comp.std.c++
    In nearly every case the implementation of the operator++(int) and operator--(int) looks like that:
    class Example {
      public:
        Example& operator++() {// or operator--
          //implementation
          return(*this);
        }
        const Example operator++(int) { // or operator--
          Example temp(*this);
          ++*this;
          return temp;
        }
    }
    Whats the sence of the possibility to overload the postfix operator?
    Why is the postfix operator not auto-implemented? 
    That would has the advantage that compiler could optimize postfix-uses (even it
     is a mistake of the programmer, that he used the postfix one).
    

    [ Dieser Beitrag wurde am 26.01.2003 um 13:35 Uhr von Lars editiert. ]



  • Original erstellt von Lars:
    **Whats the sence of the possibility to overload the postfix operator?
    Why is the postfix operator not auto-implemented?
    That would has the advantage that compiler could optimize postfix-uses (even it
    is a mistake of the programmer, that he used the postfix one).
    **

    ich glaube das die sich ähnliche gedanken zu c++98 gemacht haben, es gibt bestimmt gute gründe wieso man die postfix version überladen darf.
    Aber mir kann eine änderung sowieso egal sein, wie oft überlade ich den, den op++?
    und mit meiner eselsbrücke langammer postfix == häslicher int dummy kann ich mir das relativ leicht merken



  • Original erstellt von Dimah:
    **
    ich glaube das die sich ähnliche gedanken zu c++98 gemacht haben, es gibt bestimmt gute gründe wieso man die postfix version überladen darf.
    Aber mir kann eine änderung sowieso egal sein, wie oft überlade ich den, den op++?
    und mit meiner eselsbrücke langammer postfix == häslicher int dummy kann ich mir das relativ leicht merken**

    Es geht ja gar nicht um Lesbarkeit oder Hässlichkeit des int-dummys, sondern um Redudanz und Optimierung. Ich hab folgende Antwort erhalten:

    One could say something similar about operator + and operator += :
    class Example
    {
    public:
       Example& operator += (const Example& other)
       {  // implementation
          return *this;
       }
    
       Example operator + (const Example& other) const
       {
          Example temp(*this);
          temp+=other;
          return temp;
       }
    };
    
    and perhaps more examples; if you allow me, let me generalize your
    proposition by using some directive to let the compiler know : "I want
    this method: auto-implement it", for example with the already existent
    'auto' keyword.
    
    An 'auto-implementation' table should be standarized (i.e. saying:
    method    auto-implemented using
    ------    ----------------------------
    ++(int)   ++()
    +         +=
    ...       ...
    
    and a standard auto-implementation for each one (left column).
    
    Your example would look like:
    
    class Example
    {
    public:
       Example& operator += (const Example& other)
       {  // implementation
          return *this;
       }
    
       auto Example operator + (const Example& other) const;
    
       Example& operator ++ ()
       {  /* your example */ }
    
       auto Example operator ++(int);
    };
    
    I think this is important in terms of optimization and readability (as
    far as the client 'see' that some operator is auto-implemented).
    
     Daniel.
    

    genau das halt ich auch für sinnvoll



  • Hallo,
    hat jetzt eigentlich schon jemand ein Vorschlag für ein foreach ohne typeof gemacht?

    Wenn nein, hier meiner:

    struct ForEachHelper
    {
        void* cur_;
        template <class T, class U>
        bool assign (T& r, U& c)
        {
            typedef typename U::iterator iter;
            if (*static_cast<iter*>(cur_) != c.end())
            {
                r = **static_cast<iter*>(cur_);
                ++*static_cast<iter*>(cur_);
                return true;
            }
            delete static_cast<iter*>(cur_);
            return false;
        }
        template <class U>
        ForEachHelper(U& cont)
        {
            typedef typename U::iterator iter;
            cur_ = (void*)new  iter(cont.begin());
        }
    };
    
    #define FOREACH(var, cont) for (ForEachHelper b(cont) ; b.assign(var,cont);)
    

    Anwendung:

    vector<int> vec;
    vec.push_back(6);
    vec.push_back(5);
    vec.push_back(4);
    int n;
    FOREACH(n, vec)
    {
        cout << n << endl;
    }
    set<string> s;
    s.insert("abc");
    s.insert("cde");
    s.insert("efg");
    string str;
    FOREACH(str, s)
    {
        cout << str << endl;
    }
    


  • lol, da hätte man eigentlich früher drauf kommen können. Statt den deklarierten Typ zu parametrisieren, einfach bei jeder Anwendung davon einen parametrisierten Cast benutzen

    nice 🙂



  • cur_ = (void*)new iter(cont.begin());

    Warum nimmst Du nen C-Style-Cast hier?
    Dass man seinen Iterator auf den Heap legen muss is performance-mäßig auch ein bisschen traurig.

    Aber ziehmlich cool eigentlich. Werd ich mal verwenden und mich vielleicht sogar dran gewöhnen 🙂



  • Warum nimmst Du nen C-Style-Cast hier?

    Um etwas Inkonsistenz reinzubringen und damit den Leser wach zu halten 😃

    Dass man seinen Iterator auf den Heap legen muss is performance-mäßig auch ein bisschen traurig

    Richtig. Das ist ein echter Nachteil. Allerdings lässt sich dieser zur Not auch umgehen. Man muss ja nur new passend überladen.



  • Was wird der nächste Standard beinhalten? Templatetypedefs?



  • *** schrieb:

    Was wird der nächste Standard beinhalten? Templatetypedefs?

    das wär mal was 👍

    //edit wow is der thread schon alt 😮



  • Wie wärs mal mit nem neuen Thread. Auf den ersten kann man leider schon nicht mehr zugreifen 😞

    Wie stehts eigentlich im Moment um C++0x? Welche Änderungen gibts? Ach, ich mach jetzt einfach nen neuen auf.



  • was beudetet eigentlich C++0x?



  • 0x steht für das Erscheinungsjahr.



  • *** schrieb:

    Was wird der nächste Standard beinhalten?

    Template-Parameter als friends deklarieren zu können



  • ness schrieb:

    *** schrieb:

    Was wird der nächste Standard beinhalten?

    Template-Parameter als friends deklarieren zu können

    auch sowas wie Hummes dirstream?



  • Weiß schon einer wann der neue Standard kommt? Kommt der schon im nächsten Jahr? Welche Compiler werden ihn unterstützen?



  • Wie wäre es denn, wenn du einfach mal den neuen Thread zu diesem Thema liest?
    http://www.c-plusplus.net/forum/viewtopic.php?t=97205


Anmelden zum Antworten