//---------------------------------------------------------------------
//
// Copyright (C) 2004 Yingle Jia
//
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// AcfLanguage.h - utilities for C++ generic programming
//
#ifndef __Acf_Language__
#define __Acf_Language__
namespace Acf {
namespace Language {
//---------------------------------------------------------------------
// IsVoid: true if the given type is "void"
template < typename T >
struct IsVoid
{
enum { Value = false };
};
template <>
struct IsVoid<void>
{
enum { Value = true };
};
//---------------------------------------------------------------------
// IsIntegral: true if the given type is a C++ integral type
template < typename T >
struct IsIntegral
{
enum { Value = false };
};
template <>
struct IsIntegral<bool>
{
enum { Value = true };
};
template <>
struct IsIntegral<sbyte>
{
enum { Value = true };
};
template <>
struct IsIntegral<byte>
{
enum { Value = true };
};
template <>
struct IsIntegral<wchar_t>
{
enum { Value = true };
};
template <>
struct IsIntegral<short>
{
enum { Value = true };
};
template <>
struct IsIntegral<ushort>
{
enum { Value = true };
};
template <>
struct IsIntegral<int>
{
enum { Value = true };
};
template <>
struct IsIntegral<uint>
{
enum { Value = true };
};
template <>
struct IsIntegral<int64>
{
enum { Value = true };
};
template <>
struct IsIntegral<uint64>
{
enum { Value = true };
};
//---------------------------------------------------------------------
// IsFloat: true if the given type is a C++ floating point type
template < typename T >
struct IsFloat
{
enum { Value = false };
};
template <>
struct IsFloat<float>
{
enum { Value = true };
};
template <>
struct IsFloat<double>
{
enum { Value = true };
};
//---------------------------------------------------------------------
// IsArithmatic: true if the given type is a integral type or floating
// point type
template < typename T >
struct IsArithmatic
{
enum { Value = IsIntegral<T>::Value || IsFloat<T>::Value };
};
//---------------------------------------------------------------------
// IsPointer: true if the given type is a pointer type
template < typename T >
struct IsPointer
{
enum { Value = false };
};
template <typename T>
struct IsPointer<T*>
{
enum { Value = true };
};
//---------------------------------------------------------------------
// IsMemberPointer: true if the given type is a member pointer type
namespace Internal {
template <class U>
struct IsMemberPointerTraits
{
enum { Value = false };
};
template <class U, class V>
struct IsMemberPointerTraits<U V::*>
{
enum { Value = true };
};
} // namespace Internal
template < typename T >
struct IsMemberPointer
{
enum { Value = Internal::IsMemberPointerTraits<T>::Value };
};
//---------------------------------------------------------------------
// IsArray: true if the given type is an array type
namespace Internal {
template <class U>
struct IsArrayTraits
{
enum { Value = false };
};
template <class U, int N>
struct IsArrayTraits<U (&)[N]>
{
enum { Value = true };
};
} // namespace Internal
template < typename T >
struct IsArray
{
enum { Value = Internal::IsArrayTraits<T>::Value };
};
//---------------------------------------------------------------------
// IsSame: true if the two given types are the same type
template < typename T, typename U >
struct IsSame
{
enum { Value = false };
};
template < typename T >
struct IsSame< T, T >
{
enum { Value = true };
};
//---------------------------------------------------------------------
// IsConvertible: true if type T is convertible to type U
template < typename T, typename U >
struct IsConvertible
{
typedef char Small;
class Big { char dummy[2]; };
static Small Test(U);
static Big Test(...);
static T MakeT();
enum { Value = (sizeof(Test(MakeT())) == sizeof(Small)) };
};
//---------------------------------------------------------------------
// IsSubclass: true if type T is a subclass of type U
template < class T, class U >
struct IsSubclass
{
enum { Value = !IsSame<const U*, const void*>::Value &&
IsConvertible<const T*, const U*>::Value && ! IsSame<const T*, const U*>::Value };
};
//---------------------------------------------------------------------
// IsSameOrSubclass: true if type T is same as or a subclass of type U
template < class T, class U >
struct IsSameOrSubclass
{
enum { Value = !IsSame<const U*, const void*>::Value &&
IsConvertible<const T*, const U*>::Value };
};
//---------------------------------------------------------------------
// NullType
struct NullType
{
};
//---------------------------------------------------------------------
// Int2Type
template <int V>
struct Int2Type
{
enum { Value = V };
};
//---------------------------------------------------------------------
// SelectType: select type with a given condition
template<bool Condition, class A, class B> // true if A, false if B
struct SelectType
{
typedef A Type;
};
template<class A, class B> // true if A, false if B
struct SelectType<false, A, B>
{
typedef B Type;
};
//---------------------------------------------------------------------
// ParamType
template < typename T >
struct ParamType
{
typedef typename SelectType<IsArithmatic<T>::Value || IsPointer<T>::Value,
T, const T&>::Type Type;
};
//---------------------------------------------------------------------
// Construct()
// - constructs the elements with the default constructors.
//---------------------------------------------------------------------
template <typename T>
inline void Construct(T* p, int count)
{
int i;
try
{
for (i = 0; i < count; i++)
{
new(p + i) T;
}
}
catch (...)
{
while (i > 0)
{
i--;
p[i].~T();
}
throw;
}
}
//---------------------------------------------------------------------
// Construct()
// - constructs the elements with the copy constructors.
//---------------------------------------------------------------------
template <typename T>
inline void Construct(T* p, int count, const T* pSrc)
{
int i;
try
{
for (i = 0; i < count; i++)
{
new(p + i) T(pSrc[i]);
}
}
catch (...)
{
while (i > 0)
{
i--;
p[i].~T();
}
throw;
}
}
//---------------------------------------------------------------------
// Destruct()
// - destructs the elements
//---------------------------------------------------------------------
template <typename T>
inline void Destruct(T* p, int count)
{
for (int i = 0; i < count; i++)
{
p[i].~T(); // destructors should never throw
}
}
//---------------------------------------------------------------------
// Copy()
// - copies n elements
//---------------------------------------------------------------------
template <typename T>
inline void Copy(const T* pSrc, T* pDst, int count)
{
if (IsArithmatic<T>::Value || IsPointer<T>::Value)
{
memcpy(pDst, pSrc, count * sizeof(T));
}
else
{
for (int i = 0; i < count; i++)
pDst[i] = pSrc[i];
}
}
//---------------------------------------------------------------------
// New()
//---------------------------------------------------------------------
template <typename T>
inline T* New(int count)
{
T* p = Acf::Alloc<T>(count);
try
{
Construct(p, count);
}
catch (...)
{
Acf::Free(p);
throw;
}
return p;
}
//---------------------------------------------------------------------
// Delete()
//---------------------------------------------------------------------
template <typename T>
inline void Delete(T* p, int count)
{
Destruct(p, count);
Acf::Free(p);
}
} // namespace Language
} // namespace Acf
#endif // #ifndef __Acf_Language__