C++程序  |  168行  |  6.02 KB

/* -*- 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__