Habemus C++14



  • Ich erwarte, daß die template variables viel TMC-Code einfacher machen werden.

    Wo es Spaß machen könnte:

    template <typename T>
    constexpr bool is_const_v = std::is_const<T>::value;
    

    Kommt dann vielleicht irgendwann parallel zu den *_t -Aliastemplates als *_v .

    Was ne beschissene Syntax, buh.

    Verstehe ich nicht. Wovon redest du?



  • Kellerautomat schrieb:

    Lambda captures expressions: Hab ich noch nie gebraucht, sinnlos? Wo sind move captures?

    auto lambda = [value=std::move(move_only_t)](){...};
    


  • 👍

    volkard schrieb:

    "Binary literals" sind unnötig.

    Geh' doch nicht immer von Dir aus.

    Kellerautomat schrieb:

    Function return type deduction: Finde ich vollkommen unnoetig, werde ich vmtl. auch nie verwenden.

    Ich finde das superpraktisch. Gerade wenn man generische Bibliotheken baut, kann man sich damit das -> decltype(ausdruck) und damit ein gewisses Maß an Duplikation sparen. Was damit auch möglich werden sollte, ist das Zurückgeben von Lambdas ohne den Umweg über std::function .

    Kellerautomat schrieb:

    Variable templates: Sehr schoen, jetzt kann ich meine Makros endlich durch Variable Templates ersetzen.

    Für dieses Feature hätt ich gerne schöne Beispiele, die es motivieren. Hab mich nämlich immer gefragt, warum wir so etwas brauchen.





  • Weiss schon jemand wie MS' Plan für den C++14 Support aussieht?



  • hustbaer schrieb:

    Weiss schon jemand wie MS' Plan für den C++14 Support aussieht?

    Bislang so: http://blogs.msdn.com/b/vcblog/archive/2014/06/11/c-11-14-feature-tables-for-visual-studio-14-ctp1.aspx





  • Arcoth schrieb:

    Was ne beschissene Syntax, buh.

    Verstehe ich nicht. Wovon redest du?

    Ich schlage vor:

    [] (x, y) { doStuff(x, y); }
    

    Aber ne, die muessen da wieder ein vollkommen unnoetiges auto reinpacken.

    Nathan schrieb:

    Kellerautomat schrieb:

    Lambda captures expressions: Hab ich noch nie gebraucht, sinnlos? Wo sind move captures?

    auto lambda = [value=std::move(move_only_t)](){...};
    

    Ganz toll, warum einfach wenns auch kompliziert geht.

    kkaw schrieb:

    Kellerautomat schrieb:

    Function return type deduction: Finde ich vollkommen unnoetig, werde ich vmtl. auch nie verwenden.

    Ich finde das superpraktisch. Gerade wenn man generische Bibliotheken baut, kann man sich damit das -> decltype(ausdruck) und damit ein gewisses Maß an Duplikation sparen. Was damit auch möglich werden sollte, ist das Zurückgeben von Lambdas ohne den Umweg über std::function .

    Vermutlich hast du Recht, was templates angeht. Die Tricks mit lambda returns sind doch nur Spielereien, die niemand braucht.

    kkaw schrieb:

    Kellerautomat schrieb:

    Variable templates: Sehr schoen, jetzt kann ich meine Makros endlich durch Variable Templates ersetzen.

    Für dieses Feature hätt ich gerne schöne Beispiele, die es motivieren. Hab mich nämlich immer gefragt, warum wir so etwas brauchen.

    Also ich hab mir einen Header gebaut, der mir Type Traits vereinfacht. Der sieht in etwa so aus:

    #define TYPE(x) typename X::type
    #define VALUE(x) X::value
    
    #define ENABLE_IF(cond, ...) TYPE(std::enable_if<cond, __VA_ARGS__>)
    #define IS_SAME(x, y) VALUE(std::is_same<x, y>)
    #define REMOVE_REFERENCE(x) TYPE(std::remove_reference<x>)
    

    Welche der folgenden liest sich schoener?

    ENABLE_IF(IS_SAME(T, REMOVE_REFERENCE(U)), T) // #1
    typename std::enable_if<std::is_same<T, typename std::remove_reference<U>::type>::value, T>::type // #2
    

    Fuer mich ganz klar #1.

    Mit variable templates brauch ich das nicht mehr.



  • Kellerautomat schrieb:

    Ich schlage vor:

    [] (x, y) { doStuff(x, y); }
    

    Aber ne, die muessen da wieder ein vollkommen unnoetiges auto reinpacken.

    Vermutlich, weil du normalerweise eh const auto& x willst und nicht auto x . Warum also die Syntax für pass by value optimieren?



  • audacia schrieb:

    Kellerautomat schrieb:

    Ich schlage vor:

    [] (x, y) { doStuff(x, y); }
    

    Aber ne, die muessen da wieder ein vollkommen unnoetiges auto reinpacken.

    Vermutlich, weil du normalerweise eh const auto& x willst und nicht auto x . Warum also die Syntax für pass by value optimieren?

    [] (const& x, const& y) { doStuff(x, y); }
    

    und nu?



  • Kellerautomat schrieb:

    [] (const& x, const& y) { doStuff(x, y); }
    

    und nu?

    Stimmt, das geht. Mir gefällt nicht, daß ich dann auch

    [] (&x, *y, **&z)
    

    schreiben kann. Aber einen formalen Einwand habe ich nicht.



  • Kellerautomat schrieb:

    audacia schrieb:

    Kellerautomat schrieb:

    Ich schlage vor:

    [] (x, y) { doStuff(x, y); }
    

    Aber ne, die muessen da wieder ein vollkommen unnoetiges auto reinpacken.

    Vermutlich, weil du normalerweise eh const auto& x willst und nicht auto x . Warum also die Syntax für pass by value optimieren?

    [] (const& x, const& y) { doStuff(x, y); }
    

    und nu?

    Gleich überall Typnamen weglassen dürfen, wo der Compiler sie sich basteln kann?

    //irgendwo außerhalb einer funktion
    sum(x,y){
       return x+y;
    }
    

    kann nur eine funktionsdefinition sein, muss zum template werden, alles geht automatisch.
    besser noch, das dumme return auch weglassen, es wird immer der befehl returnt, und wer tatsächlich mal den ungewöhnlichen fall hat, daß er void return will, kann auch ganz einfach erzwingen.

    //irgendwo außerhalb einer funktion
    sum(x,y){
       x+y;
    }
    
    //irgendwo außerhalb einer funktion
    add(x,y){
       x+=y;
       ;//oder "return;" oder "{}"
    }
    //natürlich wird x automatisch per referenz übergeben, weils sonst keinen sinn ergibt.
    

    für einzeiler braucht man natürlich keine geschweiften klammern, das wird dann endlich konsistent zu if/for/while und so.

    sum(x,y)
      x+y;
    

    nee, ich bin froh, manchmal noch ein auto zu sehen. viel mehr wie "so ein destruktor wird automatisch aufgerufen, ohne, daß was im code steht" sollte nicht stillschweigend passieren. c++11 ist da schon arg übertrieben.



  • typename std::enable_if<std::is_same<T, typename std::remove_reference<U>::type>::value, T>::type // #2
    

    ➡

    std::enable_if_t<std::is_same<T, std::remove_reference_t<U>>{}, T> // #3 (C++14)
    

    und nu?

    Defaultmäßig sollte auto&& als placeholder-Typ verwendet werden, genau wie bei terse range-based for loops (-std=c++1z bei Clang ):

    for (a : {1, 2, 3})
        std::cout << a;
    

    Demnach sollte

    [] (a, b) {}
    

    äquivalent sein zu

    [] (auto&& a, auto&& b) {}
    

    Ich finde im Übrigen

    #define var auto&&
    

    ganz praktisch.



  • Also, in Rust machen die das mit den Closures so, dass der Typ hergeleitet wird:

    fn call(dings: int, bums: |int|) {
        bums(dings);
    }
    
    fn main() {
        call(23, |x| {
            //   ^^^
            // Typ von x muss ich hier nicht angeben
            println!("x ist {}", x);
        });
        println!("x ist {}", x);
    }
    

    Das ist doch auch eine nette Lösung. Vielleicht lässt sich das ja nach C++ übertragen, wenn Concepts kommen:

    template<class Func> where Callable<Func(int)>
    void call(int dings, Func bums) {
        bums(dings);
    }
    
    int main() {
        call(23, [](x){
            std::cout << "x ist " << x << std::endl;
        });
    }
    

    Also: Statt auto , auto const& oder auto&& einfach das nehmen, das der Aufrufer erwartet. (?)



  • audacia schrieb:

    Kellerautomat schrieb:

    [] (const& x, const& y) { doStuff(x, y); }
    

    und nu?

    Stimmt, das geht. Mir gefällt nicht, daß ich dann auch

    [] (&x, *y, **&z)
    

    schreiben kann. Aber einen formalen Einwand habe ich nicht.

    Schreibst es ja auch falsch. 🤡

    [] (& x, * y, **& z)
    

    @volkard: Ich stimme dir in keinem einzigen Punkt zu. Je kuerzer, desto besser.

    @Arcoth: #3 kommt an #1 auch nicht ran. Das tolle an Makros ist, dass man die std-Traits garnicht aus dem std-namespace holen muss, um sie ohne std:: verwenden zu koennen. Und mit einem #undef Header kann man die Makros auch wieder wegraeumen. Makros > all

    Zu Lambdas: Ob das nun per default auto oder auto&& heisst, ist ne ganz andere Frage und mir nicht so wichtig. Hauptsache kurz.



  • Kellerautomat schrieb:

    Je kuerzer, desto besser.

    <°)))o>< <°)))o>< <°)))o><



  • Ach Leute, geht bitte Lisp programmieren anstatt hier sinnlos rumzunerven.
    Danke.



  • Networking haben sie wohl komplett aufgegeben, abgesehen von diesem URI Kram den niemand braucht. 😞



  • braucht alles seine zeit.
    vor allem gibts kaum was brauchbares an "prior art" - maximal noch ASIO, aber ob die so optimal wäre, weiss nicht.

    wichtig ist dass sie jetzt in kürzeren abständen immer wieder was machen wollen, und dass die compiler/compiler-entwickler so weit sind dass sie die dinge auch in endlicher zeit integrieren können, also nicht immer jahrelang hinterherhinken.



  • hustbaer schrieb:

    braucht alles seine zeit.
    vor allem gibts kaum was brauchbares an "prior art" - maximal noch ASIO, aber ob die so optimal wäre, weiss nicht.

    ASIO würde ich so, wie es ist, auch nicht in den Standard übernehmen. io_service hat zu viele Aufgaben und wird an zu vielen Stellen benötigt. Die Sockets benötigen den auch, wenn man nur die synchronen Operationen benutzt.

    Viele Teile von ASIO sind auch kaum sinnvoll standardisierbar, weil sie Windows- oder Posix-spezifisch sind oder bloß OpenSSL wrappen.

    Um sinnvoll Daten durch die Gegend zu schieben bräuchte man auch noch so etwas wie iostream , aber in benutzbar. Dafür gibt es genau gar keine C++-Vorbilder.

    Außerdem wären Coroutinen nicht schlecht. Dafür gibt es in Boost auch ein Vorbild. Hoffentlich setzen sich keine "resumable"-Schlüsselwörter oder so Blödsinn durch.


Anmelden zum Antworten