//here we relay the decoding to the special packet decoder.
UInt16 PacketHandler::Decode(UInt16 type, Byte *pBuf, UInt16 iBufSize)
{
Iter iter, end = decoders.end();
if((iter = decoders.find(type)) != end)
{
return *iter->Decode(pBuf, iBufSize);
}
throw PacketDecoderNotFoundException(type);
}
The question is if UInt16 type can be known at compile time.. I guess it
cannot... but I tried to see how close I could get... And the solution
involves a function pointer array, instead of a case, but I do get rid of
the virtual function....
I have no idea how this will perform, so you will have to give it a go...
with a profiler...
Hope this will help you in any way ...
Jesper
enum encoder {
kSpecialDecoderOne=0,
kSpecialDecoderTwo
};
typedef short (*DecodePtr) (void*,short);
struct UnknownPackage {
};
template <encoder T>
struct Decoder
{
encoder T;
short Decode(void *pBuf, short iBufSize);
};
template <>
struct Decoder<kSpecialDecoderOne>
{
encoder kSpecialDecoderOne;
static short Decode(void *pBuf, short iBufSize)
{
std::cout << "Decoding message type 1"<<std::endl;
return 1;
}
};
template <>
struct Decoder<kSpecialDecoderTwo>
{
encoder kSpecialDecoderTwo;
static short Decode(void *pBuf, short iBufSize)
{
std::cout << "Decoding message type 2"<<std::endl;
return 1;
}
};
struct PacketHandler {
short Decode(encoder typeI, void *pBuf, short iBufSize)
{
static DecodePtr typeArray[]={ (&Decoder<kSpecialDecoderOne>::Decode) ,
&Decoder<kSpecialDecoderTwo>::Decode };
static unsigned long arraySize = sizeof(typeArray)/sizeof(DecodePtr);
//array boundscheck
if (typeI>=0 && typeI<arraySize)
return typeArray[typeI](pBuf,iBufSize);
throw UnknownPackage();
}
};
int main(int /*argc*/,char*[] /*argv*/)
{
PacketHandler packetHandler;
packetHandler.Decode(kSpecialDecoderOne,0,0);
packetHandler.Decode(kSpecialDecoderTwo,0,0);
return 0;
}
"Martin" <pe*******@hotmail.com> wrote in message
news:9b**************************@posting.google.c om...
Well I guess I should explain myself.
I have a "packet decoder" that uses the Strategy pattern.
There's a hash_map which maps packet types to PacketDecoders(which all
inherits from AbstractDecoder).
struct AbstractDecoder
{
virtual UInt16 Decode(Byte *pBuf, UInt16 iBufSize) = 0;
};
struct SpecialDecoderOne : public AbstractDecoder
{
virtual UInt16 Decode(Byte *pBuf, UInt16 iBufSize)
{
std::cout << "Decoding message type 1"<<std::endl;
return 1;
}
};
typedef stdext::hash_map<const
UInt16,AbstractDecoder*,std::equal_to<UInt16> > DecoderStrategy;
typedef DecoderStrategy::const_iterator Iter;
DecoderStrategy decoders;
//here we relay the decoding to the special packet decoder.
UInt16 PacketHandler::Decode(UInt16 type, Byte *pBuf, UInt16 iBufSize)
{
Iter iter, end = decoders.end();
if((iter = decoders.find(type)) != end)
{
return *iter->Decode(pBuf, iBufSize);
}
throw PacketDecoderNotFoundException(type);
}
I'd ultimately like to lose the virtual functions by using the inherit
from template parameter trick
template <class T>
class AbstractDecoder
{
public:
UInt16 Decode(Byte *pBuf, UInt16 iBufSize)
{
T *pT = static_cast<T*>(this);
return pT->DecodeImpl(pBuf, iBufSize);
}
protected:
UInt16 DecodeImpl(Byte *pBuf, UInt16 iBufSize)
{
std::cout <<"OOPS no DecodeImpl in subclass"<<std::endl;
}
};
struct SpecialDecoderOne : public AbstractDecoder<SpecialDecoderOne>
{
UInt16 DecodeImpl(Byte *pBuf, UInt16 iBufSize)
{
std::cout << "Decoding message type 1"<<std::endl;
return 1;
}
};
The reason to this is I want the decoder to be as efficient as
possible short
of doing a big switch(type) over all the different packets.
I will accept if it's not possible to achieve this in anyway though
:-)
edit: please overlook any missing "const" :-P