decltype mit verschachtelten Funktionsaufrufen



  • Hallo zusammen,

    ich frage ich mich, ob
    man in folgendem Code das decltype von baz_type kürzen kann:

    #include <iostream>
    #include <tuple>
    
    int main() {
    	auto foo = []{return 1;};
    	typedef decltype(foo()) foo_type;
    	auto bar = [](const foo_type&){return 'c';};
    	typedef decltype(bar(foo())) bar_type;
    	auto baz = [](const bar_type&){return 1.0;};
    	typedef decltype(baz(bar(foo()))) baz_type;
    	auto quux = [](const baz_type&){};
    }
    

    Muss man wirklich alle Funktionsaufrufe ineinanderschachteln oder kann ich das (mit Hilfe eines typedefs?) kürzen?

    Gruß,
    XSpille



  • Sieht jetzt vielleicht nicht kürzer aus, aber ist immerhin lineare statt quadratische Komplexität:

    template<typename T> T creator();
    
    int main()
    {
        //...
        typedef decltype(baz(creator<bar_type>())) baz_type;
    }
    


  • dafür gibt es std::declval. Mit std::declval<T>() kann man einen Ausdruck vom Typ T erzeugen zwecks Einsatz innerhalb von decltype. In welchem Header das definiert wird, weiß ich gerade nicht. Vielleicht <utility>? Es kann aber sein, dass Dein Compiler das noch nicht kennt.

    Einen Ersatz kann man sich so bauen:

    #include <type_traits>
    template<class T>
    typename std::add_rvalue_reference<T>::type declval();
    

    wobei aber die tatsächliche Verwendung außerhalb von nicht-evaluierten Ausdrücken einen Fehler darstellt. add_rvalue_reference wird hier eingesetzt, um unvollständige und abstrakte Typen als auch void zu unterstützen. Lvalues kann man aber auch damit erzeugen. Beispiel: declval<int&>() erzeugt ein Lvalue Ausdruck vom Typ int.



  • Danke euch beiden! 👍

    @krümelkacker:
    Genau das habe ich gesucht. Mein Compiler (GCC 4.6.1) unterstützt es auch.

    Auch mit utility als Header lagst du richtig:
    http://en.cppreference.com/w/cpp/utility/declval


Anmelden zum Antworten