interesting templates

This is a discussion on interesting templates within the C++ Programming forums, part of the General Programming Boards category; I have some code here that has a lot of separate classes with the exact same interface: class ThreadX { ...

  1. #1
    Registered User
    Join Date
    Jun 2004
    Posts
    201

    interesting templates

    I have some code here that has a lot of separate classes with the exact same interface:

    class ThreadX { void WaitFor() {} };
    class ThreadY { void WaitFor() {} };
    class ThreadZ { void WaitFor() {} };

    For the rest they have nothing in common, no base class.
    Then there's some class That holds pointers to these instances:

    class ThreadHolder
    {
    ThreadX* x;
    ThreadY* y;
    ThreadZ* z;
    };

    In the destructor every separate object is deleted by the same template of code:

    if (x != NULL)
    {
    x->WaitFor();
    delete x;
    x = 0;
    }

    and so hundreds of the exact same lines.(the real code does more)

    So I created a template function now that deletes these objects in a generic way.

    template<class T>
    void TerminateThread(T*& thread)
    {
    if (thread != NULL)
    {
    thread->WaitFor();
    delete thread;
    thread = 0;
    }
    }

    Works nicely, but I want more.

    I now have lots of lines like this:

    TerminateThread(x);
    TerminateThread(y);
    TerminateThread(z);

    Can I put this in a loop somehow so I can finally reduce this code to a line of 20?

    something like:

    array a = { x, y, z };
    for each item in array
    TerminateThread(a[i]);

    I can't figure out how to declare the array because the threads are all different classes.

    I hope I'm clear

  2. #2
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Inherit all of the classes from the same base class, something like 'ThreadBase'. Then store the threads as an array of base class pointers. So instead of:
    Code:
    ThreadX x;
    ThreadY y;
    ThreadZ z;
    Do something like this:
    Code:
    ThreadBase *Threads[3];
    ThreadBase[0]=new ThreadX;
    That's approximate but I think it's a good idea.
    benforbes@optusnet.com.au
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  3. #3
    Registered User
    Join Date
    Jun 2004
    Posts
    201
    yeas, ok that's what I wanted to do, but then I would have to change all the Thread classes.
    I was thinking if there's a way with templates for instance so I only have to change this one source file and not the whole project.

  4. #4
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    I think it would be a better idea to change all the Thread classes to have the same base class. It wouldn't take that long, because the changes need be made to only a small portion of the code, and plus, it's good programming practise to share a base class between classes that have some common functionality.

    All you need to do is add the base class in, like so:
    Code:
    class ThreadBase
    {
    public:
        ThreadBase() {}
        ~ThreadBase() {}
    };
    And change the Thread class declarations like so:
    Code:
    class ThreadX : public ThreadBase
    {
    public:
    //etc
    Now, you can store a pointer to a ThreadBase object, and when you 'delete' it, the magical V-Tables (or whatever) will ensure that the appropriate destructor for that particular object is run.

    I don't think a solution with templates exists here, but someone else may know of a way.
    benforbes@optusnet.com.au
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  5. #5
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    You can kind of do it by storing a list of function objects. Something like this

    Code:
    #include <vector>
    #include <iostream>
    using namespace std;
    
    class basic_thread_action
    {
    public:
        virtual void del() = 0;
        virtual ~basic_thread_action() { }
    };
    
    
    template<typename ThTyp_>
    class thread_action : public basic_thread_action
    {
    public:
        typedef ThTyp_ Thread;
    
        thread_action(Thread* t)
            : thread(t)
        {    }
    
        virtual void del()
        {
            if (thread != NULL)
            {
                delete thread;
                thread = 0;
            }
        }
    private:
        Thread* thread;
    };
    
    class thread_holder
    {
        typedef std::vector<basic_thread_action*> container;
        typedef container thread_container;
    
        thread_container threads;
    public:
        ~thread_holder()
        {
            typedef container::iterator TI;
    
            for (TI i = threads.begin(); i != threads.end(); ++i) 
            {
                (*i)->del();
                delete *i;
            }
        }
    
        template<typename ThTyp_>
        void register_thread(ThTyp_* t)
        {
            threads.push_back(new thread_action<ThTyp_>(t));       
        }
    };
    
    class Thread_a
    {
    public:
        ~Thread_a()
        {
            std::cout << "Thread_a << " << std::endl;
        }
    };
    
    class Thread_b
    {
    public:
        ~Thread_b()
        {
            std::cout << "Thread_b" << std::endl;
        }
    };
    
    int main()
    {
        thread_holder th;
    
        th.register_thread(new Thread_a());
        th.register_thread(new Thread_b());
    
        return 0;
    }
    Last edited by okinrus; 07-12-2004 at 06:29 PM.

  6. #6
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    That's a pretty good solution. I would personally just use base classes, but your method would be good in other circumstances, when you have to indiscriminately store objects with no commonality.
    benforbes@optusnet.com.au
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  7. #7
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    I think there might be another way as well.

    Code:
    #include <vector>
    #include <iostream>
    
    struct Thread_a
    {
        ~Thread_a()
        {
            std::cout << "Thread_a" << std::endl;
        }
    };
    
    struct Thread_b
    {
        ~Thread_b()
        {
            std::cout << "Thread_b" << std::endl;
        }
    };
    
    template<typename ThTyp>
    struct ThreadStore
    {
        std::vector<ThTyp*> threads;
    
        ~ThreadStore()
        {
            typedef std::vector<ThTyp*>::iterator TI;
    
            for (TI i = threads.begin(); i != threads.end(); ++i)
                delete *i;
        }
    };
    
    struct ThreadHolder
    {
        template<typename ThTyp>
        static void registerThread(ThTyp* t)
        {
            static ThreadStore<ThTyp> threads;
            threads.threads.push_back(t);
        }
    
    };
    
    
    
    int main(void)
    {
        ThreadHolder::registerThread(new Thread_a());
        ThreadHolder::registerThread(new Thread_b());
        ThreadHolder::registerThread(new Thread_a());
        return 0;
    }
    The code should create for Thread_a and Thread_b two different static instantiation functions with the two different vectors then when the destructors get called it's possible to get what appears to be polymorphic behavior.

  8. #8
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    So if I understand templates correctly, a registerThread() function will be created for each type that is used with it. Is that correct?
    benforbes@optusnet.com.au
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  9. #9
    Registered User
    Join Date
    Aug 2003
    Posts
    470
    This is my understanding. You can kind of check what happens by printing out the size if vector threads. On my compiler you get 0, 0, 1.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A few interesting tools...
    By Mad_guy in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 03-10-2009, 07:07 PM
  2. Templates from DLL or static library problem
    By mikahell in forum C++ Programming
    Replies: 2
    Last Post: 01-01-2008, 01:49 AM
  3. Questions about Templates
    By Shamino in forum C++ Programming
    Replies: 4
    Last Post: 12-18-2005, 12:22 AM
  4. templates and inheritance problem
    By kuhnmi in forum C++ Programming
    Replies: 4
    Last Post: 06-14-2004, 03:46 AM

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