detecting basic types

L

Lasse Skyum

Hi All,

Is it possible to detect (at compile-time) if an item is a basic type (int,
float, double,...) or an instance of a class/struct?

I'm thinking something like: (obviosly this isn't working...)

template<typename T>
CMyFileClass::Serialize(T &x)
{
#if IS_BASIC_TYPE(T)
// handle basic type
#else
// handle a class inherited from my CSerializable class
#endif
}


BTW, I'm writing serialization of data for a gameproject....

Thanks for any help!
Lasse
 
T

Thierry Miceli

Lasse Skyum said:
Hi All,

Is it possible to detect (at compile-time) if an item is a basic type (int,
float, double,...) or an instance of a class/struct?

Andrei Alexandrescu is adressing this issue in his book "Modern C++ design",
see section 2.10.2 "Detection of Fundamental Types".

Thierry
 
H

Howard Hinnant

Lasse Skyum said:
Hi All,

Is it possible to detect (at compile-time) if an item is a basic type (int,
float, double,...) or an instance of a class/struct?

I'm thinking something like: (obviosly this isn't working...)

template<typename T>
CMyFileClass::Serialize(T &x)
{
#if IS_BASIC_TYPE(T)
// handle basic type
#else
// handle a class inherited from my CSerializable class
#endif
}

You might be interested in the type traits library at boost:

http://www.boost.org/libs/type_traits/index.htm

This library has been submitted for standardization and accepted into
the first library technical report:

http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1424.htm

A close facsimile of this lib has shipped with Metrowerks CodeWarrior
for the past 3 years. It lives in namespace Metrowerks in the header
<msl_utility>.

These libs might be used like:

#include <msl_utility>

using namespace Metrowerks;

struct CSerializable {};

template <class T>
struct CMyFileClass
{
void Serialize(T& x);
private:
void Serialize(T& x, int2type<false>);
void Serialize(T& x, int2type<true>);
};

template<typename T>
inline
void
CMyFileClass<T>::Serialize(T &x)
{
Serialize(x, int2type<is_arithmetic<T>::value>());
}

template<typename T>
void
CMyFileClass<T>::Serialize(T &x, int2type<true>)
{
// handle basic type
}

template<typename T>
void
CMyFileClass<T>::Serialize(T &x, int2type<false>)
{
compile_assert<is_convertible<T, CSerializable>::value>
must_be_convertible_to_CSerializable;
// handle a class inherited from my CSerializable class
}

I wrote this using the Metrowerks tools so that I could check it before
I posted. The boost or std::tr1 interface would be very close.

-Howard
 
J

Jeff Schwab

Lasse said:
Hi All,

Is it possible to detect (at compile-time) if an item is a basic type (int,
float, double,...) or an instance of a class/struct?

There's a *great* treatment of this topic in the Josuttis templates book:

http://www.josuttis.com/tmplbook/tmplbook.html

Basically, you make a "traits" class to hold compile-time info about
each type, and specialize as needed. Making complicated decisions based
on the traits info is certainly possible; try googling for
"metaprogramming."

Good luck,
Jeff
 
L

Lasse Skyum

Thanks a lot guys, I've solved it now!

By looking at some documents about "meta-programming" I worked something
together.
 
J

Jeff Schwab

Lasse said:
Thanks a lot guys, I've solved it now!

By looking at some documents about "meta-programming" I worked something
together.

Would you care to post it?
 
L

Lasse Skyum

Would you care to post it?

Sure thing, please let me know if you have any additional ideas!


// This is the base-class for my Input-streams
class CZS_IStream
{
public:
virtual int ReadBytes(void *pBytes,int iByteCount)=0;

template<typename T>
bool Read(T &v)
{
CZS_Serializer<T> s; // This is where the trick happens...
return s.Read(this,v);
}

};

// Every time data is read/written it goes through a version of
CZS_Serializer.
// This is the "default" one if none other is defined.
template<typename T>
class CZS_Serializer
{
public:
bool Read(CZS_IStream *pS,T &v){return v.Serialize_Read(pS);}
bool Write(CZS_OStream *pS,T &v){return v.Serialize_Write(pS);}
};

// All basic types are registered as "binary-types" by implementing a
CZS_Serializer for them, that
// uses ReadBytes and WriteBytes instead of the
Serialize_Read/Serialize_Write functions.

#define ZS_REGISTER_BINARYTYPE(CAClass) \
template<>class CZS_Serializer<CAClass> \
{ \
public: \
bool Read(CZS_IStream *pS,T &v){return
pS->ReadBytes(&v,sizeof(T))==sizeof(T);} \
bool Write(CZS_OStream *pS,const T &v){return
pS->WriteBytes(&v,sizeof(T));} \
}; \

ZS_REGISTER_BINARYTYPE(char)
ZS_REGISTER_BINARYTYPE(unsigned char)
ZS_REGISTER_BINARYTYPE(signed char)
ZS_REGISTER_BINARYTYPE(int)
ZS_REGISTER_BINARYTYPE(unsigned int)
ZS_REGISTER_BINARYTYPE(long)
ZS_REGISTER_BINARYTYPE(unsigned long)
ZS_REGISTER_BINARYTYPE(__int8)
ZS_REGISTER_BINARYTYPE(__int16)
ZS_REGISTER_BINARYTYPE(__int32)
ZS_REGISTER_BINARYTYPE(__int64)
ZS_REGISTER_BINARYTYPE(float)
ZS_REGISTER_BINARYTYPE(double)
ZS_REGISTER_BINARYTYPE(long double)
ZS_REGISTER_BINARYTYPE(bool)
 

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
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top