Re: The CRTP pattern and member function pointer template parameter
Olivier Langlois wrote:
I wanted to achieve static polymorphism with the CRTP pattern to
create a base class for encapsulating the thread creation with the
pthread API.
IMHO mapping a thread to a C++ object is a bad idea, since neither obeys the
lifetime of the other, but that's a different topic. I'd still suggest
Boost.Thread at least as suggestion how to do it, it (mostly) follows the
same principles that guided the design of iostreams with regard to the
relation between fstream and a file.
What I was trying was:
template<class D, void *(D::*F)()>
class ThreadBase
{
static void *start_routine(void *arg);
};
template<class D, void *(D::*F)()>
void *ThreadBase<D,F>::start_routine(void *arg)
{
D *pThis = static_cast<D *>(arg);
return (pThis->*F)();
}
where I could have defined a derived class:
class Derived : public ThreadBase<Derived,&Derived::Run>
^^^^^^^^^^^^^
The marked part is the problem.
What you could do is that you turn the inheritance around, which also
assures that (assuming you do something in the ctor of ThreadBase) the
object which performs the operation is already completely constructed:
template<class D, void *(D::*F)()>
class ThreadBase: private D // or public?
{ ... };
However, if you go that far, you could as well make it a function:
template<class D>
ThreadHandle create_thread( D& d, void *(D::*F)())
{ }
Or, you could extend it to anything callable like a function:
template<class Callable>
ThreadHandle create_thread( Callable c)
{ }
...which would allow you to use {boost,tr1}::function. However, then you are
not far away from Boost.Thread, so you can as well use that. Take care that
the functor passed in is copied though, use boost::ref() if that's not what
you want.
As a temporary fix, I am going to remove the second parameter F from
the template ThreadBase and hardcode which member function gets called
like this:
template<class D>
void *ThreadBase<D>::start_routine(void *arg)
{
D *pThis = static_cast<D *>(arg);
return pThis->Run();
}
but I find it sad to lose the flexibility to choose at compile time
which member function will be called.
Two things:
1. It is normal with polymorphism that the baseclass dictates which function
is called, whether it is static or dynamic.
2. You are passing an argument to the static start_routine(). For CRTP, you
would not make it static but a normal member and then simply
use 'static_cast<Derived*>(this)'. Eventually, both are the same, but it is
simply more convenient like this.
Uli
--
Sator Laser GmbH
Gesch??ftsf??hrer: Ronald Boers, Amtsgericht Hamburg HR B62 932
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]