Pointer innerhalb Klasse auf Memberfunktion



  • Offensichtlich habe ich Probleme mich richtig auszudrücken. Ich denke nicht, dass ich hier etwas versuche, was ich nicht richtig begreife.

    Zugegeben: Mit Templates arbeite ich gewöhnlich nicht, daher auch die letzte Frage. Aber Threads oder Sockets habe ich schon oft erstellt, nur eben nie für eine Methode innerhalb einer Klasse.

    Das ich die Möglichkeit der statischen Deklaration oder des externen Aufrufs habe, wusste ich bereits vorher. Ich dachte nur, dass mir jemand noch eine geschicktere Variante verraten kann.
    Man darf da nicht so kurzsichtig sein. Die Frage sollte irgendwo auch darauf abzielen, dass jemandem vielleicht ein generell anderer Lösungsweg einfällt; das war nicht unbedingt beschränkt auf den Methoden-Pointer.



  • FrEEzE2046 schrieb:

    Ich habe mich derweil auch mal ein bisschen mit boost::function auseinander gesetzt. Es dient zwar überhaupt nicht mehr meiner Problemlösung, aber schien mir doch recht interessant zu sein.

    ...

    Was mich jetzt interessieren würde, ist, wie man denn den übergebenen Funktionstyp "auswertet" (falsches Wort, schon klar 😉

    Hier ist eine halbwegs überschaubare Implementierung auf Basis von C++0x: click. Sie ist nicht perfekt und vielleicht auch nicht besonders leserlich aber das Prinzip sollte klar werden.


  • Administrator

    FrEEzE2046 schrieb:

    Offensichtlich habe ich Probleme mich richtig auszudrücken.

    Kann sein, zum Teil empfand ich es als sehr verwirrend, wie du geantwortet hast. Ich bin mir das oft gewohnt davon, wenn der andere sich nicht so gut im Thema auskennt.

    FrEEzE2046 schrieb:

    Ich denke nicht, dass ich hier etwas versuche, was ich nicht richtig begreife.

    Ich kann es nicht genau beurteilen, solange ich nicht deinen genauen Wissensstand kenne, was man eben mit der Literatur zumindest teilweise hätte feststellen können 😉

    FrEEzE2046 schrieb:

    Man darf da nicht so kurzsichtig sein. Die Frage sollte irgendwo auch darauf abzielen, dass jemandem vielleicht ein generell anderer Lösungsweg einfällt; das war nicht unbedingt beschränkt auf den Methoden-Pointer.

    Im allgemeinen geht man über eine statisch oder globale Funktion und übergibt einen Zeiger auf eine Struktur. Das geht auch gar nicht gross anders, weil es so von den Betriebsystemen vorgeschrieben ist.
    Die Threading Bibliothek kapselt dieses nicht so schöne Aussehen und gibt einem ein allgemeingültiges Interface. Was zum Beispiel eben auch boost::thread macht.

    Nun ist halt die Frage, was willst du genau? Steigst du auf boost::thread um oder kapselst du lieber deine Threading Bibliothek und erstellst dir eine eigene, was aber mit ziemlich viel Arbeit verbunden ist. Sowas zu erstellen ist nicht gerade von heute auf morgen fertig und man sollte dabei schon auch in Templates gefestigt sein.

    Was genau möchtest du also nun von uns hören? Wenn du mehr über Templatemetaprogrammierung wissen willst, dann kann ich dir auch ein oder zwei Bücher empfehlen.

    Grüssli



  • Sebastian Pizer schrieb:

    Hier ist eine halbwegs überschaubare Implementierung auf Basis von C++0x: click. Sie ist nicht perfekt und vielleicht auch nicht besonders leserlich aber das Prinzip sollte klar werden.

    Was ich nicht verstehe ist diese Zeile:

    template<typename R, typename ... P>
    

    Ich bekomme da logischerweiße einen Compilerfehler

    missing ',' before '...'
    

    Was genau soll obige Deklaration bedeuten? Eine nichtdefinierte Parameterliste? Wenn ja, wie spreche ich die übergebenen Werte an?





  • Ich benutze das Visual Studio 2008 Team System. Gibt es eine Möglichkeit C++ 0x Code dort zu kompilieren?

    Laut MSDN Blog sollen Variadic Templates ja nicht mal in VS 10 möglich sein. Welcher Compiler kann das schon jetzt?





  • Ja, dass habe ich mittlerweile schon gesehen. Boost::Function benutzt aber keine variable Parameterliste für seine templates.

    Ich muss allerdings zugeben, dass ich die Vorgehensweiße dort nicht ganz verstehe. Mich interessiert die herangehensweiße schon sehr muss ich sagen. Allerdings möchte ich ungern a) einen anderen Compiler konfigurieren, zu mal ich Windows-User bin und b) einen "Standard" nutzen, der (noch) keiner ist.

    Zudem geht auch boost anders an die Thematik heran. Fragt sich nur wie ...



  • .........

    class keksdose
    {
    public:
      void startthread(void *arg)
      {
        threaddata t;
        t.this_pointer = this;
        t.arg = arg;
        t.function = &keksdose::myfunction;
        CreateThread(0, 0, proxy, this, 0, 0);
      }
    private:
      struct threaddata
      {
        void (keksdose::*function)(void *);
        void *arg;
        keksdose *this_pointer;
      };
      DWORD STDCALL proxy(void *vptr)
      {
        threaddata *t = static_cast<threaddata *>(vptr);
        t->this_pointer->*(t->function)(t->arg);
        return 0;
      }
      void myfunction(void *arg)
      {
         for (;;)
           Sleep(1000);
      }
    };
    

    ka ob das läuft



  • Sebastian Pizer schrieb:

    Vom GCC unterstützte C++0x Sprachfeatures.
    Status der C++0x-Std-Library Implementierung (libstdc++).

    Laut MSDN unterstützt das Visual Studio 2008 nach Installation des Visual C++ Feature Packs auch Variadic Templates( siehe: tuple Class ).

    Bei mir will die Syntax aber so noch nicht funktionieren. Kann da jemand was zu sagen?



  • FrEEzE2046 schrieb:

    Bei mir will die Syntax aber so noch nicht funktionieren. Kann da jemand was zu sagen?

    Nein. Man könnte bestenfalls raten was da "so noch nicht funktioniert". Wenn du den Code postest, der nicht funktioniert (am besten mit der Fehlereldung zusammen), dann sind die Chancen gleich viel besser dass dir jeman helfen kann.

    Siehe auch hier.



  • FrEEzE2046 schrieb:

    Laut MSDN unterstützt das Visual Studio 2008 nach Installation des Visual C++ Feature Packs auch Variadic Templates

    Da irrst Du Dich. Das was auf deren Webseite steht ist "nur" Dokumentation und kein kompilierbarer Code. Die haben dort "..." stehen, um zu zeigen, dass man tuple<> so benutzen kann, als wäre es ein variadisches Template. Es ist aber keins, weil sie die noch nicht unterstützen -- auch noch nicht in der aktuellsten Beta-Version.

    Ich habe schon ein PDF von hier verlinkt, was genau beschreibt, wie versch. Dinge (function, tuple, ...) zur Zeit ohne variadische Templates implementiert werden und wie sich die Implementierung mit variadischen Templates stark vereinfachen lässt. Du hast es anscheinend nicht sorgfältig genug gelesen.

    Nebenbei: Hier gibt's ein paar nette Artikel zur Benutzung von Threads unter C++0x.



  • Sebastian Pizer schrieb:

    Ich habe schon ein PDF von hier verlinkt, was genau beschreibt, wie versch. Dinge (function, tuple, ...) zur Zeit ohne variadische Templates implementiert werden

    Wenn du das hier meinst:

    Doch das habe ich mir sorgfältig angeschaut, aber auch dort benutzen sie doch '...'

    siehe:

    template<typename... Args> struct count;
    

    Oder meinstest du ein anderes PDF?


  • Administrator

    @FrEEzE2046,
    Am Anfang des PDFs wird aber erklärt, wie man es bisher in den C++ Bibliotheken gemacht hat. Und genau so macht es auch Boost.Function, Boost.Bind usw.
    Zudem wird auf Boost.Preprocessor verwiesen, was man zur Hilfe heranziehen kann, was bei Boost für das Simulieren von variadic templates auch gemacht wird.

    Grundsätzlich steht alles da am Anfang von Kapitel 2. Es ist sehr kurz gehalten, aber fasst es eigentlich vollständig zusammen.

    Grüssli


  • Administrator

    Sorry für den Doppelpost, aber da schon einige Zeit vergangen ist, wollte ich nicht nur ein Edit machen. Hier noch ein kurzes dahingerotztes Beispiel 🙂

    #include <iostream>
    
    #include <boost/preprocessor.hpp>
    
    #define MY_MACRO_TEMPLATE_TYPES(z, n, data) , typename T##n
    #define MY_MACRO_TEMPLATE_ARGS(z, n, data) , T##n const& arg##n
    #define MY_MACRO_TEMPLATE_OUTPUT(z, n, data) << arg##n
    
    #define MY_MACRO_PRINT_FUNCTION(z, n, data) \
    template<typename T0 BOOST_PP_REPEAT_FROM_TO(1, n, MY_MACRO_TEMPLATE_TYPES, data)>\
    void print(T0 const& arg0 BOOST_PP_REPEAT_FROM_TO(1, n, MY_MACRO_TEMPLATE_ARGS, data)) \
    { \
        std::cout BOOST_PP_REPEAT(n, MY_MACRO_TEMPLATE_OUTPUT, data) ;\
    } \
    
    #define MY_MACRO_CREATE_PRINT_FUNCTIONS(n) \
        BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(n), MY_MACRO_PRINT_FUNCTION, _)
    
    MY_MACRO_CREATE_PRINT_FUNCTIONS(10)
    
    int main()
    {
        print("Hello", " World", '!', '\n', "Test: ", 443, '\n');
    
        return 0;
    }
    

    Die maximale Anzahl an Parametern ist 10. Also quasi Variadic Templates beschränkt auf 10 Parametern. Das ganze präsentiert an einer print Funktion. Sieht hässlich aus, nicht? 😃
    Variadic Templates aus C++0x werden diese Hässlichkeiten hoffentlich entfernen können 😉

    Grüssli



  • Ich steig einfach nicht dahinter, wie man die Template-Argumente zunächst auf "typename Signature" begrenzt und dann intern in die Spezialisierungen aufsplittet.

    Mir ist klar, dass das mit irgendwelchen Makro-Verschachtelungen geschieht, aber ich versteh noch nicht wie. Würde mich aber sehr interessieren.

    Das einzige was ich in der Richtung hinbekomme ist sowas hier:

    #define PP_REPEAT_1( param )	param ## 0
    #define PP_REPEAT_2( param )	param ## 0, param ## 1
    #define PP_REPEAT_3( param )	param ## 0, param ## 1, param ## 2
    
    #define ENUM_PARAMS( count, param )			PP_REPEAT_##count( param )
    
    template<ENUM_PARAMS( 3, typename T )> class function {};
    

    Das ändert aber nichts daran, dass ich

    function<int, int, int> f;
    

    Benutzen muss. Wie kann das anders gelöst werden?


  • Administrator

    Hier mal ein wenig Beispielcode (Achtung, sehr viele wichtige Dinge wie Kopierkonstruktoren usw. usf. wurden weggelassen):

    #include <memory>
    
    template<typename T>
    struct FunctorImpl;
    
    template<typename R>
    struct FunctorImpl<R()>
    {
        typedef R ResultType;
    
        virtual R call() const;
        virtual FunctorImpl* clone() const;
    };
    
    template<typename R, typename P0>
    struct FunctorImpl<R(P0)>
    {
        typedef R ResultType;
        typedef P0 Parameter0;
    
        virtual R call(Parameter0) const;
        virtual FunctorImpl* clone() const;
    };
    
    template<typename R, typename P0, typename P1>
    struct FunctorImpl<R(P0, P1)>
    {
        typedef R ResultType;
        typedef P0 Parameter0;
        typedef P1 Parameter1;
    
        virtual R call(Parameter0, Parameter1) const = 0;
        virtual FunctorImpl* clone() const = 0;
    };
    
    // usw. halt mit Makros aktuell
    
    template<typename ImplT, typename FuncT>
    struct FunctorHandler
        : ImplT
    {
    private:
        FuncT m_func;
    
    public:
        FunctorHandler(FuncT func)
            : m_func(func)
        {
        }
    
    public:
        typename ImplT::ResultType call() const
        {
            return m_func();
        }
    
        typename ImplT::ResultType call(typename ImplT::Parameter0 p0) const
        {
            return m_func(p0);
        }
    
        typename ImplT::ResultType call(typename ImplT::Parameter0 p0, typename ImplT::Parameter1 p1) const
        {
            return m_func(p0, p1);
        }
    
        // usw. mit Makros
    
        FunctorHandler* clone() const
        {
            return new FunctorHandler(*this);
        }
    };
    
    template<typename T>
    struct Functor
    {
    private:
        typedef FunctorImpl<T> Impl;
        std::auto_ptr<Impl> m_impl;
    
    public:
        template<typename FuncT>
        Functor(FuncT func)
            : m_impl(new FunctorHandler<Impl, FuncT>(func))
        {
        }
    
    public:
        typename Impl::ResultType operator ()() const
        {
            return m_impl->call();
        }
    
        typename Impl::ResultType operator ()(typename Impl::Parameter0 p0) const
        {
            return m_impl->call(p0);
        }
    
        typename Impl::ResultType operator ()(typename Impl::Parameter0 p0, typename Impl::Parameter1 p1) const
        {
            return m_impl->call(p0, p1);
        }
    
        // usw. mit Makros
    };
    
    // ...
    
    #include <iostream>
    
    int foo(int x, double y)
    {
        return static_cast<int>(x * y);
    }
    
    int main()
    {
        Functor<int(int, double)> functor(&foo);
        return functor(4, 22.3);
    }
    

    Es gibt auch noch andere Vorgehensweisen, habe das jetzt nur so mehr oder weniger schnell aus dem Kopf zusammengebaut. Ich hoffe allerdings, dass es das eigentliche Prinzip erklärt.

    Grüssli



  • FrEEzE2046 schrieb:

    Das ändert aber nichts daran, dass ich

    function<int, int, int> f;
    

    Benutzen muss. Wie kann das anders gelöst werden?

    Defaultparameter 🙂

    EDIT:
    Ja, camper hat natürlich recht. Weiss auch nicht wie ich darauf gekommen bin, dass man Klassentemplates überladen könnte.



  • LordJaxom schrieb:

    Kurz: Das liegt daran, dass Du ein Template mit drei Parametern erzeugst. Boost.Function hat aber mehrere Templates, eines mit 0, eines mit einem, eines mit zwei, ...., eines mit zehn Parametern. Die Templates heissen alle gleich, weshalb es für Dich so aussieht als wäre es variadic.

    Zudem gäbe es noch die Möglichkeit für alle Parameter Defaults anzugeben.

    Ja, dass ist mir schon klar. Entschuldige, ich hab mich wieder unpräzise ausgedrückt.

    Beispiel:

    struct nil;
    
    template<typename R = nil, typename T0 = nil, typename T1 = nil, typename T2 = nil> class function;
    
    template<> class function<> {};
    template<typename R> class function<R> {};
    template<typename R, typename T0> class function<R, T0> {};
    template<typename R, typename T0, typename T1> class function<R, T0, T1> {};
    
    // Trotzdem:
    function<int, int> f1;
    function<int, int, int> f2;
    

    Ich frage mich halt, wie es gemacht wird einen Funktionstyp anzugeben (z.B. void (int, double) und den dann intern dem Template:

    template<typename R = nil /*void*/, typename T0 = nil /*int*/, typename T1 = nil /*double*/> class function.
    

    zuzuordnen.


  • Mod

    Klassentemplates können nicht überladen werden.


Anmelden zum Antworten