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



  • Eine Funktionalität die ich ich aus Pascal kenne ist, dass man Objekte (Sei es struct oder class) in den namensraum (scope) einbinden kann.

    Ein Beispiel wie ich es meine:

    struct A
    {
     int x;
    };
    
    void irgendEineFunktion()
    {
     A a;
     using a;
     x = 1;
    }
    

    Ist soetwas in der Art in C++ möglich?
    Denn mit using kann man anscheinend nur Namensräume oder Klassen, jedoch keine Objekte in den scope einbinden.



  • a ist doch schon im Scope von irgendEineFunktion. Vielleicht meinst du stattdessen using A::x;?



  • Um den Unterschied nochmal zu verdeutlichen.

    void irgendEineFunktion()
    {
     A a;
     a.x = 1;
    }
    
    void irgendEineFunktion()
    {
     A a;
     using a;
     x = 1;
    }
    

    Wenn man using auf namespaces anwendet kann man ja auch die ganze Unterstruktur einbinden:

    void irgendEineFunktion()
    {
     std::cout << "bla";
    }
    
    void irgendEineFunktion()
    {
     using namespace std;
     cout << "bla";
    }
    


  • Nein, so etwas wie die with-Anweisung gibt es in C++ (und auch in C) nicht - man muß immer ein Objekt explizit bei jedem Zugriff angeben.


  • Mod

    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 )
    


  • 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.


  • Mod

    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? Dass der Bezeichner B65 nicht mehr verfügbar ist? Die absolut unplausible Möglichkeit dass der Compiler die Schleife nicht wegoptimiert?

    for( auto const& motion : motions )
    		with( n = motion.get_normal(), t = motion.get_tangent() )
    		{
    			/// Berechungen anstellen, die mehrfaches verwenden der Tangente und Normale erfordern
    		}
    

    Ich frage mich gerade ob es auch eine Definition mit range-based for gibt. Aber wie abspeichern? Durch std::reference_wrapper o.ä. klappt es nicht für rvalues...



  • Das ersetzt aber gerade eben nicht die Delphi-Syntax.
    Bei dir muß man ja dann noch explizit einmalig jeden Member zuweisen.
    Nur zur Klarstellung, so müsste die Syntax aussehen:

    A a;
    with(a)
    {
      x = 1;
    }
    

    In Delphi benutzt man diese Schreibweise hauptsächlich für die Zuweisung an Eigenschaften (properties).
    Und in C# z.B. gibt es für die Initialisierung eine ähnliche Möglichkeit:

    A a = new A { X = 1 }; // X muß aber auch hier eine Eigenschaft sein
    


  • 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.


Log in to reply