bonj said:
Hello
How do I declare a template class such that the template class T must
implement a certain interface?
I have a related question. Which is considered better for writing
interfaces in C++: abstract base classes, or templates - and why? I.e.
when is one preferable over the other?
Let's suppose I want to specify an interface for classes that can
"pickle" themselves; i.e. read/write their state information to a "flat"
binary storage (for serialization, or message-passing, etc.) It occurs
to me that there are two ways one could do this:
typedef std::vector<unsigned char> ByteVector;
struct IPickle
{
virtual void Pickle(ByteVector &bv) = 0; // write state to vector
virtual void Unpickle(ByteVector &bv) = 0; // get state from vector
};
then one could create classes that inherit from IPickle and implement
the functions:
class PickleSample : public IPickle
{
...
};
Or, one could use the Curiously Recurring Template Pattern:
template <class T> struct TPickle
{
void Pickle(ByteVector &bv) {T:
ickle(bv);}
void Unpickle(ByteVector &bv) {T::Unpickle(bv);}
};
class PickleSample : public TPickle<PickleSample>
{
...
};
What are the pros and cons of each? The ABC approach lets you do things
like this:
void PickleAndSendMessage(IPickle *p_obj)
{
ByteVector bv;
p_obj->Pickle(bv);
SendMessageUsingSomeTransport(&bv[0], bv.size());
}
i.e. where PickleAndSendMessage() can work with any object that
"exposes" the IPickle interface. If I understand correctly, this would
not be possible with the CRTP approach. I thought maybe that an
advantage of the CRTP would be that it would be easier to "bolt on"
Pickle functionality to an existing class, e.g.:
// pre-existing class
class Blorf
{
int foo, bar;
public:
// some functions here
};
// new class with pickling
class PickleBlorf : public Blorf, public TPickle<PickleBlorf>
{
public:
PickleBlorf() : Blorf() {}
void Pickle(ByteVector &bv) {/*write foo and bar into bv*/}
void Unpickle(ByteVector &bv) {/*get foo and bar from bv*/}
};
but then I realized that this could just as easily be done using the ABC
approach - instead of inheriting from TPickle<PickleBlorf> above, you
would just inherit from IPickle instead.
So what's the downside of the ABC approach? What am I missing about the
Curiously Recurring Template Pattern that's got everybody talking about
it? Why not just use ABCs instead? Is it the fact that they lead to
the creation of a vtable? Is that such a big deal?
Thanks,