template woes

This is a discussion on template woes within the C++ Programming forums, part of the General Programming Boards category; Hi! I was browsing through some open source apps and came across this snippet which I can't quite bend my ...

  1. #1
    Registered User
    Join Date
    Feb 2002
    Posts
    32

    template woes

    Hi!

    I was browsing through some open source apps and came across this snippet which I can't quite bend my head around. I'd really like a little help from the gurus in here=)

    Code:
      template <typename Ret, Ret (torrent::Download::*func)()>
      void               call()                                                { (m_download.*func)(); }

  2. #2
    C/C++ homeyg's Avatar
    Join Date
    Nov 2004
    Location
    Louisiana, USA
    Posts
    209
    Here's so the gurus can read the code:

    Code:
    template <typename Ret, Ret (torrent::Download::*func)()> void call()                                                
    { 
         (m_download.*func)(); 
    }

  3. #3
    Registered User
    Join Date
    Feb 2002
    Posts
    32
    he thanks

  4. #4
    #define WORLD "sad place" LinuxCoder's Avatar
    Join Date
    Mar 2006
    Location
    Portugal
    Posts
    89
    I'm far from being a guru, specially when it comes to templates, but anyway that looks like a callback definition that would be a way of calling different function methods in torrent:ownload objects. Suppose you have a simple Download class in a namespace torrent for instance:
    Code:
    namespace torrent
    {
        class Download
        {
        public:
            float fn1();
            float fn2();
            int otherfn();
            someclass somefn();
    
        }; //class Download
    
    }; //namespace torrent
    Code:
    template <typename Ret, Ret (torrent::Download::*func)()> void call()                                                
    { 
         (m_download.*func)(); 
    }
    Now i believe that the code you posted is a templated function inside a class, i believe that 'm_download' object in there to be a class member since it is not an argument to the function being declared. By putting this into a template you are allowing the simple function to call methods in the object without having the need for a set of different calls (one for every possible return type), thus allowing you to use the same simple syntax to call functions returning int, float or even class types. Taking the example i gave you before:
    Code:
    //Declare a function pointer to point to otherfn() method
    int (torrent::Download::*fn_ptr)() = &torrent::Download::otherfn;
    
    //Declare a function pointer to the fn1() member method
    float (torrent::Download::*fn_ptr2)() = &torrent::Download::fn1;
    
    /* if A is an object from the class where the template call is declared
        it contains a torrent::Download object which is m_download */
    
    A.call<int,fn_ptr>();        // will call m_download.otherfn() which returns an int
    A.call<float,fn_ptr2>();     // will call m_download.fn1() which will return a float
    Of course these are just some ideas as from such a tiny small snippet of code it's quite hard to guess exactly how and when it is being used.

    Sorry for the huge post, i hope this helps a tad. Cheers
    Last edited by LinuxCoder; 04-03-2006 at 09:08 AM.

  5. #5
    Registered User
    Join Date
    Feb 2002
    Posts
    32

    Post

    I realize that my post wasn't at all that informative, and that your reply was really insightful since I didn't provide much information at all.

    Code:
    namespace Core {
       
    class Download {
        public:
    
         template <typename Ret, Ret (torrent::Download::*func)()>
         void               call()                                   { (m_download.*func)(); }
    
        Torrent::Download m_download;
    };
    };
    I'm thinking that the purpose is to make all void X() members of Torrent::Download appear as members of Core::Download without using proper inheritance. I think that Torrent::Download appears somewhere inside a library, whereas Core::Download is a class in the client. If this is true, why is it done like this? Why isn't inheritance used instead? Of course, I may still not have understood it.

    The program is rtorrent and libtorrent by the way.

    Thanks for your reply:)
    Last edited by Hubas; 04-03-2006 at 09:46 AM.

  6. #6
    #define WORLD "sad place" LinuxCoder's Avatar
    Join Date
    Mar 2006
    Location
    Portugal
    Posts
    89
    'm thinking that the purpose is to make all void X() members of Torrent::Download appear as members of Core::Download without using proper inheritance
    Well, if that was the case there was no point in using the template. The template is there to allow you to call all functions in torrent::Download taking no arguments, no matter what the return from that function is. If you were only caring for void X() calls you'd go with basic
    Code:
    void call(void (torrent::Download::*func)()) { (m_download.*func)(); }
    First off you would opt for inheritance if you were to change/expand the behavior of the original class. This class does not provide any change to the original functionalities nor does it expand them, instead what it does is allowing you to abstract the call to object methods by providing a common interface.

    Code:
    /* Suppose torrent::Download has these methods  NOTICE the != return types */
    
    void (torrent::Download::*pause_cmd)() = &torrent::Download::pause;
    bool (torrent::Download::*stop_cmd)() = &torrent::Download::stop;
    int (torrent::Download::*start_cmd)() = &torrent::Download::start;
    
    ...
    
    // At somepoint you define a myObj to contain a given torrent::Download Object
    Core::Download myObj(some_torrent_download_obj);
    
    ...
    
    /* Then later on, probably in some UI function or so */
    
    switch(some_input){
        case STOP: myObj.call<void,stop_cmd>(); break;
        case PAUSE: myObj.call<void,pause_cmd>(); break;
        case START:
        default: cmd = myObj.call<int,start_cmd>();
    }
    If you look at this example you'll see that with the same kind of function you can call different methods on a given object, the only thing is that in that template function you must ignore the return from the original class method since call() is declared void there.
    This is what it seems to me, it's possible that it is used in a totally different manner. Hope this helps some more

    Cheers.

  7. #7
    Registered User
    Join Date
    Feb 2002
    Posts
    32
    I think you nailed it! Thank you for your insights=) I'll run off and find some books to brush up on my skills.

    Cheers,

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Specialising a member function with a template template parameter
    By the4thamigo_uk in forum C++ Programming
    Replies: 10
    Last Post: 10-12-2007, 04:37 AM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. template woes
    By rippascal in forum C++ Programming
    Replies: 6
    Last Post: 03-25-2002, 10:16 PM
  5. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 11:54 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21