"using" auf Objekt um es in den scope einzubinden möglich?



  • Arcoth schrieb:

    volkard schrieb:

    Arcoth schrieb:

    Th69 schrieb:

    Nein, so etwas wie die with-Anweisung gibt es in C++ (und auch in C) nicht

    Naja, man kann es künsteln:

    #define with(...) for( bool B65 = true; B65;) for( auto&& __VA_ARGS__; B65; B65 = false )
    

    Bitte mit Anwendungsbeispiel, damit man sehen kann, ob's den Auwand wert ist.

    Welchen Aufwand?

    Den Aufwand, das neue Kunstrukt überhaupt zu lernen.

    Arcoth schrieb:

    Dass der Bezeichner B65 nicht mehr verfügbar ist? Die absolut unplausible Möglichkeit dass der Compiler die Schleife nicht wegoptimiert?

    Nee, aus B65 hätte man schon noch nen eindeutigen Namen basteln können, und daß0 der Compiler schummelt, davon mag ich gerade nicht ausgehen.

    Arcoth schrieb:

    for( auto const& motion : motions )
    		with( n = motion.get_normal(), t = motion.get_tangent() )
    		{
    			/// Berechungen anstellen, die mehrfaches verwenden der Tangente und Normale erfordern
    		}
    
    for( auto const& motion : motions )
    		{
    			auto = motion.get_normal();
    			auto t = motion.get_tangent();
    			/// Berechungen anstellen, die mehrfaches verwenden der Tangente und Normale erfordern
    		}
    //da hat mir with gar nicht viel gebracht.
    

    Hier scheint es was zu bringen.

    With UserHandler.GetUser.First.User
        .FirstName="Stefan"
        .LastName="Karlsson"
        .Age="39"
        .Sex="Male"
        .Occupation="Programmer"
        .UserID="0"
    end with
    

    Ob man in C++ häufiger so lange Initialisierungslisten hat oder ob man es abkürzen würde mit

    {
        auto& u=UserHandler.GetUser.First.User;
        u.FirstName="Stefan";
        u.LastName="Karlsson";
        u.Age="39";
        u.Sex="Male";
        u.Occupation="Programmer";
        u.UserID="0";
    }
    

    weiß ich nicht.


  • Mod

    Nee, aus B65 hätte man schon noch nen eindeutigen Namen basteln können

    Das war ausschließlich demonstrativ gewählt. Daher ist das kein Argument gegen die Idee an sich.

    daß der Compiler schummelt, davon mag ich gerade nicht ausgehen.

    Jedes Optimierungslevel bei Clang und GCC ab 1 optimiert die Schleife vollständig weg. Und Schummelei würde ich das nicht nennen. as-if.

    Ich würde das in meinem Projekt auch nie nutzen. Es ist aber ganz witzig.



  • Macros dieser Art vermeide ich. Die können oft zu fürchterlichen Fehlermeldungen führen wenn was nicht stimmt.

    Also gibts keinen with Ersatz.
    Bleibt nur die nächst beste Methode es zu handhaben:

    struct langerStructName
    {
     int x;
    };
    
    void funktionDerMacht(langerStructName &mitNochLängerenVariablenNamen)
    {
     langerStructName &v = mitNochLängerenVariablenNamen;
     v.x = 1;
    }
    

  • Mod

    Oder seit C++11:

    auto &v = mitNochLängerenVariablenNamen;
    

    Bzw.

    #define var auto&&
    
    var v = mitNochLaengerenVariablenNamen;
    

    Ich sollte weniger Metal hören, während ich hier antworte.



  • Ist diese Syntax angenehm?

    int main() {
      std::vector<int> v;
      WITH(v,
           push_back(1),
           push_back(2),
           resize(5,3));
      for (int i : v)
        printf("%d\n", i);
    }
    

    http://ideone.com/UDdtBj

    #define CONCATENATE(arg1, arg2)  CONCATENATE1(arg1, arg2)
    #define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
    #define CONCATENATE2(arg1, arg2) arg1##arg2
    
    #define FOR_EACH_1(what, arg, x) what(arg, x)
    #define FOR_EACH_2(what, arg, x, ...) what(arg, x) FOR_EACH_1(what, arg, __VA_ARGS__);
    #define FOR_EACH_3(what, arg, x, ...) what(arg, x) FOR_EACH_2(what, arg, __VA_ARGS__);
    #define FOR_EACH_4(what, arg, x, ...) what(arg, x) FOR_EACH_3(what, arg, __VA_ARGS__);
    #define FOR_EACH_5(what, arg, x, ...) what(arg, x) FOR_EACH_4(what, arg, __VA_ARGS__);
    #define FOR_EACH_6(what, arg, x, ...) what(arg, x) FOR_EACH_5(what, arg, __VA_ARGS__);
    #define FOR_EACH_7(what, arg, x, ...) what(arg, x) FOR_EACH_6(what, arg, __VA_ARGS__);
    #define FOR_EACH_8(what, arg, x, ...) what(arg, x) FOR_EACH_7(what, arg, __VA_ARGS__);
    
    #define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
    #define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__) 
    #define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N 
    #define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
    
    #define FOR_EACH_(N, what, arg, x, ...) CONCATENATE(FOR_EACH_, N)(what, arg, x, __VA_ARGS__)
    #define FOR_EACH(what, arg, x, ...) FOR_EACH_(FOR_EACH_NARG(x, __VA_ARGS__), what, arg, x, __VA_ARGS__)
    
    #define DO_WITH(var,action) var.action;
    #define WITH(var, ...) ([&]{ FOR_EACH(DO_WITH, var, __VA_ARGS__) }())
    

  • Mod

    Ist diese Syntax angenehm?

    Edit: Die Syntax ist akzeptabel* - nur ist deine Lösung furchtbar. Vor allem weil sie schon bei Templates aussteigen sollte. Aber auch, weil WITH(v, push_back(1)); schon nicht mehr funktioniert.

    Zeig erstmal die Boost.PP-Lösung.

    * Es wird mit dieser Syntax jedoch das Template-Argument Problem nie gelöst.



  • Lustig, dass man in C++ doch recht nahe an die ursprüngliche Syntax herankommt, wenn auch mit Einschränkungen.

    Der Nutzen eines with -Schlüsselworts wäre mir allerdings viel zu klein, um so eine "Lösung" zu bemühen... Wenn ein ähnliches Feature nützlich ist, dann eher was in Richtung benannte Parameter à la Boost.Parameter, aber auch da steckt mir etwas viel schwarze Magie drin.

    Für die Realität ist volkards letzter Code definitiv vorzuziehen -- nicht nur weil es ohne Probleme und in allen Fällen funktioniert, sondern weil auch andere C++-Programmierer den Code verstehen.


  • Mod

    Eine simple Lösung die auch mit Template-Argument-Listen funktioniert ist

    #define BOOST_PP_VARIADICS 1 /// Für Clang. Boost.PP erlaubt Clang die variadic macros default-mäßig noch nicht
    #include <boost/preprocessor/list/for_each.hpp>
    #include <boost/preprocessor/variadic/to_list.hpp>
    
    #define VARIADIC_IDENTITY( ... ) __VA_ARGS__
    #define DO_CALL(_, d, call) (d). VARIADIC_IDENTITY call ;
    #define WITH(d, ...) { BOOST_PP_LIST_FOR_EACH( DO_CALL, d, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) }
    

    Beispiel:

    #include <iostream>
    
    struct A
    {
    	template<int... i>
    	void f()
    	{
    		for(auto g : {i...})
    			std::cout << g << ' ';
    		std::cout << std::endl;
    	}
    };
    
    int main()
    {
    	A v;
    	WITH( v,
    	     (f<4,5>()),
    	     (f<51, 8, 7>()) );
    }
    

    Warum das with-statement übrigens zu einem Ausdruck werden soll, ist mir unklar - ein compound-statement reicht doch?



  • ...


  • Mod

    Swordfish schrieb:

    h4x0r! Mir graut's vor dir!

    Kann jemand dem Fisch mal eins mit dem Totschläger verpassen?



  • ...



  • Swordfish schrieb:

    Vorsichtig. Ganz, ganz vorsichtig, h4x0r. § 26 StGB.

    Seit wann ist es rechtswidrig jemanden dazu anzustiften Fische zu töten? :p
    Dann müsste man ja alle Chefs von Fischerei betrieben verhaften.



  • ...



  • Swordfish schrieb:

    Fischereibetrieb schreibt man zusammen.

    Ja, tut man. Das war...
    Ach, egal.



  • ...


  • Mod

    Vorsichtig.

    Hihi, ein Möchtegern.

    Kannst du mich fachlich noch übertreffen? 🙂



  • ...



  • Arcoth schrieb:

    Ist diese Syntax angenehm?

    Edit: Die Syntax ist akzeptabel* - nur ist deine Lösung furchtbar. Vor allem weil sie schon bei Templates aussteigen sollte.

    Bitte genauer spezifizieren: Wer Methoden aufruft, bei denen zwei oder mehr Template-Argumente explizit angegeben werden müssen, hat unter Umständen Schwierigkeiten. Durchschnittliche Auftritte pro 1000 Zeilen Sourcecode: 0.00.

    Aber auch, weil WITH(v, push_back(1)); schon nicht mehr funktioniert.

    Oh wie schrecklich, WITH mit einem Argument war der Hauptanwendungszweck!!!
    Lässt sich trivial anpassen, falls das wirklich jemand braucht.

    Zeig erstmal die Boost.PP-Lösung.

    Das bisschen Makrogedöns ist mit der Skriptsprache deiner Wahl (!=C++) mit einem Einzeiler generiert.

    * Es wird mit dieser Syntax jedoch das Template-Argument Problem nie gelöst.

    Methodenaufrufe mit expliziten Template-Argumenten (sogar Mehrzahl!) kommen so selten vor, dass dafür die Syntax im General Case zu verschlimmern nicht für mich nicht vertretbar ist.

    Arcoth schrieb:

    Warum das with-statement übrigens zu einem Ausdruck werden soll, ist mir unklar - ein compound-statement reicht doch?

    Wegen dem im Gegensatz zu Template-Argumenten normalen Use-Case:

    A v;
        if (rand()%2)
          WITH( v,
               (f<4,5>()),
               (f<51, 8, 7>()) ); // das Semikolon ist das Problem
        else
          WITH( v,
               (f<4,6>()),
               (f<51, 5, 7>()) );
    

  • Mod

    Wer Methoden aufruft, bei denen zwei oder mehr Template-Argumente explizit angegeben werden müssen, hat unter Umständen Schwierigkeiten.
    [...] Methodenaufrufe mit expliziten Template-Argumenten (sogar Mehrzahl!) kommen so selten vor, dass dafür die Syntax im General Case zu verschlimmern nicht für mich nicht vertretbar ist.

    Genau - bei der ursprünglichen Definition!

    Nun lass uns mal ein Zeichen ändern:

    #define DO_CALL(_, d, call) (d) VARIADIC_IDENTITY call ;
    

    Dieses Feature ist gar nicht ausschließlich für Funktionen ausgelegt. Und daher kann folgendes mitunter auftreten:

    WITH( Resolver<value_type, Args...>:: template,
    	     (    parser<T, U>::parse(stream)),
    	     (ray_parser<T, U>::parse(stream)) );
    

    !=C++

    Wir sind in einem Standard-C++ Board. Es interessiert keine Skriptsprache.
    (Mit Boost.PP kann es ein Zweizeiler werden, ist dann aber nicht ganz so hübsch wie meine Variante - verwendet BOOST_PP_TUPLE_REM und BOOST_PP_TUPLE_SIZE )

    Edit: Übrigens, hast du gemeint du könntest die Makro-Definitionen mit einer Skript-Sprache verkürzen?

    das Semikolon ist das Problem

    Und genau das Semikolon sollste doch gar nicht hinschreiben. Oder ist das so irreführend und ambig?
    (Ich bin nur ein ganz klein wenig skeptisch ob das Lambda vollständig geinlined wird 🙂 )


  • Mod

    Arcoth schrieb:

    (Ich bin nur ein ganz klein wenig skeptisch ob das Lambda vollständig geinlined wird 🙂 )

    Clang 3.4 optimiert ab -O2, GCC 4.9 ab -O. Genügt, oder?


Anmelden zum Antworten