blob: bc7cc0b9e352ca2475ea2bb2586de7afc4f10703 [file] [log] [blame]
/* -*- c++ -*- */
/*
* Copyright (C) 2009 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef ANDROID_ASTL_TYPE_TRAITS_H__
#define ANDROID_ASTL_TYPE_TRAITS_H__
// GNU C++ compiler?
#ifndef __GNUG__
#error "__GNUG__ is not defined"
#endif
#ifdef _T
#error "_T is defined"
#endif
// In this files is a set of templates used to instrospect some
// template arguments properties.
//
// For instance to provide a specialized implementation of a template
// function foo<_T> when its template argument is a pointer type:
//
// template<typename _T> void foo(_T val) { // template function
// const bool is_pointer = is_pointer<_T>::value;
// __foo<is_pointer>::foo(val); // concrete impl
// }
//
// template<bool> struct __foo {
// template<typename _T> static void foo(_T val) {
// .... default implementation ...
// }
// }
//
// Specialization of the above when the bool parameter is true (i.e is
// a pointer)
//
// template<> struct __foo<true> {
// template<typename _T> static void foo(_T val) {
// .... pointer specific implementation ...
// }
// }
//
namespace std {
template<typename _T, _T _value>
struct integral_constant
{
static const _T value = _value;
typedef _T value_type;
typedef integral_constant<_T, _value> type;
};
// typedef for true and false types
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
// is_integral
template<typename> struct is_integral : public false_type { };
#define DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(_Type) \
template<> struct is_integral<_Type>: public true_type { }; \
template<> struct is_integral<_Type const>: public true_type { }; \
template<> struct is_integral<_Type volatile>: public true_type { }; \
template<> struct is_integral<_Type const volatile>: public true_type { };
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(bool)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(char)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(signed char)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(unsigned char)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(wchar_t)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(short)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(unsigned short)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(int)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(unsigned int)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(long)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(unsigned long)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(long long)
DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE(unsigned long long)
#undef DEFINE_IS_INTEGRAL_TO_TRUE_TYPE_FOR_TYPE
// is_floating_point
template<typename> struct is_floating_point : public false_type { };
#define DEFINE_IS_FLOATING_POINT_TO_TRUE_TYPE_FOR_TYPE(_Type) \
template<> struct is_floating_point<_Type>: public true_type { }; \
template<> struct is_floating_point<_Type const>: public true_type { }; \
template<> struct is_floating_point<_Type volatile>: public true_type { }; \
template<> struct is_floating_point<_Type const volatile>: public true_type { };
DEFINE_IS_FLOATING_POINT_TO_TRUE_TYPE_FOR_TYPE(float)
DEFINE_IS_FLOATING_POINT_TO_TRUE_TYPE_FOR_TYPE(double)
DEFINE_IS_FLOATING_POINT_TO_TRUE_TYPE_FOR_TYPE(long double)
#undef DEFINE_IS_FLOATING_POINT_TO_TRUE_TYPE_FOR_TYPE
// is_pointer
template<typename> struct is_pointer : public false_type { };
template<typename _T>
struct is_pointer<_T*>: public true_type { };
template<typename _T>
struct is_pointer<_T* const>: public true_type { };
template<typename _T>
struct is_pointer<_T* volatile>: public true_type { };
template<typename _T>
struct is_pointer<_T* const volatile>: public true_type { };
// is_arithmetic
template<typename _T>
struct is_arithmetic : public integral_constant<bool, (is_integral<_T>::value || is_floating_point<_T>::value)> { };
// is_scalar
// TODO: Add is_enum and is_member_pointer when gcc > 4.1.3
template<typename _T>
struct is_scalar
: public integral_constant<bool, (is_arithmetic<_T>::value || is_pointer<_T>::value)> { };
// Substitution Failure Is Not An Error used in is_pod.
struct sfinae_types
{
typedef char one;
typedef struct { char arr[2]; } two;
};
// Only classes will match the first declaration (pointer to member).
// TODO: newer version of gcc have these is_class built in.
template<typename _T> sfinae_types::one test_pod_type(int _T::*);
template<typename _T> sfinae_types::two& test_pod_type(...);
template<typename _T>
struct is_pod: public integral_constant<bool, sizeof(test_pod_type<_T>(0)) != sizeof(sfinae_types::one)> { };
template<typename _T>
struct is_class: public integral_constant<bool, sizeof(test_pod_type<_T>(0)) == sizeof(sfinae_types::one)> { };
} // namespace std
#endif // ANDROID_ASTL_TYPE_TRAITS_H__