1
2// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
3// Hinnant & John Maddock 2000.
4// Use, modification and distribution are subject to the Boost Software License,
5// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt).
7//
8// See http://www.boost.org/libs/type_traits for most recent version including documentation.
9
10
11#ifndef BOOST_TT_IS_ENUM_HPP_INCLUDED
12#define BOOST_TT_IS_ENUM_HPP_INCLUDED
13
14#include <boost/type_traits/intrinsics.hpp>
15#include <boost/type_traits/integral_constant.hpp>
16#ifndef BOOST_IS_ENUM
17#include <boost/type_traits/add_reference.hpp>
18#include <boost/type_traits/is_arithmetic.hpp>
19#include <boost/type_traits/is_reference.hpp>
20#include <boost/type_traits/is_convertible.hpp>
21#include <boost/type_traits/is_array.hpp>
22#ifdef __GNUC__
23#include <boost/type_traits/is_function.hpp>
24#endif
25#include <boost/type_traits/detail/config.hpp>
26#if defined(BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION)
27# include <boost/type_traits/is_class.hpp>
28# include <boost/type_traits/is_union.hpp>
29#endif
30#endif
31
32namespace boost {
33
34#ifndef BOOST_IS_ENUM
35#if !(defined(__BORLANDC__) && (__BORLANDC__ <= 0x551))
36
37namespace detail {
38
39#if defined(BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION)
40
41template <typename T>
42struct is_class_or_union
43{
44 BOOST_STATIC_CONSTANT(bool, value = ::boost::is_class<T>::value || ::boost::is_union<T>::value);
45};
46
47#else
48
49template <typename T>
50struct is_class_or_union
51{
52# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))// we simply can't detect it this way.
53 BOOST_STATIC_CONSTANT(bool, value = false);
54# else
55 template <class U> static ::boost::type_traits::yes_type is_class_or_union_tester(void(U::*)(void));
56
57# if BOOST_WORKAROUND(__MWERKS__, <= 0x3000) // no SFINAE
58 static ::boost::type_traits::no_type is_class_or_union_tester(...);
59 BOOST_STATIC_CONSTANT(
60 bool, value = sizeof(is_class_or_union_tester(0)) == sizeof(::boost::type_traits::yes_type));
61# else
62 template <class U>
63 static ::boost::type_traits::no_type is_class_or_union_tester(...);
64 BOOST_STATIC_CONSTANT(
65 bool, value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(::boost::type_traits::yes_type));
66# endif
67# endif
68};
69#endif
70
71struct int_convertible
72{
73 int_convertible(int);
74};
75
76// Don't evaluate convertibility to int_convertible unless the type
77// is non-arithmetic. This suppresses warnings with GCC.
78template <bool is_typename_arithmetic_or_reference = true>
79struct is_enum_helper
80{
81 template <typename T> struct type
82 {
83 BOOST_STATIC_CONSTANT(bool, value = false);
84 };
85};
86
87template <>
88struct is_enum_helper<false>
89{
90 template <typename T> struct type
91 {
92 static const bool value = ::boost::is_convertible<typename boost::add_reference<T>::type, ::boost::detail::int_convertible>::value;
93 };
94};
95
96template <typename T> struct is_enum_impl
97{
98 //typedef ::boost::add_reference<T> ar_t;
99 //typedef typename ar_t::type r_type;
100
101#if defined(__GNUC__)
102
103#ifdef BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION
104
105 // We MUST check for is_class_or_union on conforming compilers in
106 // order to correctly deduce that noncopyable types are not enums
107 // (dwa 2002/04/15)...
108 BOOST_STATIC_CONSTANT(bool, selector =
109 ::boost::is_arithmetic<T>::value
110 || ::boost::is_reference<T>::value
111 || ::boost::is_function<T>::value
112 || is_class_or_union<T>::value
113 || is_array<T>::value);
114#else
115 // ...however, not checking is_class_or_union on non-conforming
116 // compilers prevents a dependency recursion.
117 BOOST_STATIC_CONSTANT(bool, selector =
118 ::boost::is_arithmetic<T>::value
119 || ::boost::is_reference<T>::value
120 || ::boost::is_function<T>::value
121 || is_array<T>::value);
122#endif // BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION
123
124#else // !defined(__GNUC__):
125
126 BOOST_STATIC_CONSTANT(bool, selector =
127 ::boost::is_arithmetic<T>::value
128 || ::boost::is_reference<T>::value
129 || is_class_or_union<T>::value
130 || is_array<T>::value);
131
132#endif
133
134#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
135 typedef ::boost::detail::is_enum_helper<
136 ::boost::detail::is_enum_impl<T>::selector
137 > se_t;
138#else
139 typedef ::boost::detail::is_enum_helper<selector> se_t;
140#endif
141
142 typedef typename se_t::template type<T> helper;
143 BOOST_STATIC_CONSTANT(bool, value = helper::value);
144};
145
146} // namespace detail
147
148template <class T> struct is_enum : public integral_constant<bool, ::boost::detail::is_enum_impl<T>::value> {};
149
150#else // __BORLANDC__
151//
152// buggy is_convertible prevents working
153// implementation of is_enum:
154template <class T> struct is_enum : public integral_constant<bool, false> {};
155
156#endif
157
158#else // BOOST_IS_ENUM
159
160template <class T> struct is_enum : public integral_constant<bool, BOOST_IS_ENUM(T)> {};
161
162#endif
163
164} // namespace boost
165
166#endif // BOOST_TT_IS_ENUM_HPP_INCLUDED
167