Template of interface?

B

bonj

Hello
How do I declare a template class such that the template class T must
implement a certain interface?

e.g.
interface IProvideID
{
int MyID;
};

template<type T>
class ListOfIDs
{
public int add(T& newitem)
{
return newitem.MyID; //(this is what I want to do)
}
};
 
S

Shezan Baig

bonj said:
Hello
How do I declare a template class such that the template class T must
implement a certain interface?

e.g.
interface IProvideID
{
int MyID;
};

template<type T>
class ListOfIDs
{
public int add(T& newitem)
{
return newitem.MyID; //(this is what I want to do)
}
};



You already did it. If the 'T' type does not have a 'MyID' member,
then ListOfIDs<T>::add(...) will fail to compile.

-shez-
 
K

Ken Hagan

Shezan said:
You already did it. If the 'T' type does not have a 'MyID' member,
then ListOfIDs<T>::add(...) will fail to compile.

Not quite. I think bonj wants to ensure that the "MyID" that the
compiler finds is IProvideID::MyID and not the MyID of a completely
unrelated interface. But that isn't much harder.

template<type T> class ListOfIDs
{
public int add(T& newItem)
{
static_cast<IProvideID&>(newItem); // insist on the interface
return newItem.MyID;
}
};

This code will fail to compile if T isn't based (perhaps indirectly)
on IProvideID.
 
M

Mike Smith

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::pickle(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,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,201
Messages
2,571,052
Members
47,656
Latest member
rickwatson

Latest Threads

Top