@@ -26,149 +26,6 @@ SOFTWARE.
26
26
27
27
*/
28
28
29
- #ifndef ARRAYSIZE2_H
30
- #define ARRAYSIZE2_H
31
-
32
- #ifndef __has_feature
33
- #define __has_feature (x ) 0 // Compatibility with non-clang compilers.
34
- #endif
35
-
36
- #if __cplusplus >= 199711L
37
- #pragma message "using Ivan J. Johnson's ARRAY_SIZE2"
38
-
39
- // Works on older compilers, even Visual C++ 6....
40
- // Created by Ivan J. Johnson, March 06, 2007
41
- // See http://drdobbs.com/cpp/197800525?pgno=1
42
- //
43
- // Pseudocode:
44
- // if x is not an array
45
- // issue a compile-time error
46
- // else
47
- // use the traditional (non-typesafe) C99 COUNTOF expression
48
- //
49
- // If the argument is any of:
50
- // object of class type, such as an std::vector
51
- // floating-point type
52
- // function pointer
53
- // pointer-to-member
54
- // then the first reinterpret_cast<> is not legal (compiler error)
55
- //
56
- // The type for check1 is chosen and named to help understand
57
- // the cause of the error, because the class name is likely to
58
- // appear in the compiler error message.
59
- //
60
- // If check1 succeeds, then the argument must be one of:
61
- // an integral type
62
- // an enumerated type
63
- // a pointer to an object
64
- // an array
65
- //
66
- // Check2 expands approximately to sizeof(check_type(x, &x)),
67
- // where check_type is an overloaded function.
68
- // Because this is purely a compile-time computation,
69
- // the function is never really called or even implemented,
70
- // but it lets the compiler apply overload resolution,
71
- // which allows further type discrimination.
72
- // There are three possibilities to consider:
73
- // x is an integral type or enumerated type.
74
- // In this case, neither of the two function overloads
75
- // is a match, resulting in a compiler error.
76
- // x is a pointer to an object.
77
- // In this case, the first argument to check_type()
78
- // is a pointer and the second one is a pointer-to-pointer.
79
- // The best function match is the first overload of check_type,
80
- // the one that returns an incomplete type (Is_pointer).
81
- // However, because Is_pointer is an incomplete type,
82
- // sizeof(Is_pointer) is not a valid expression,
83
- // resulting in a compiler error.
84
- // x is an array.
85
- // In this case, the first argument to check_type()
86
- // is an array and the second is a pointer-to-array.
87
- // A pointer-to-array is *NOT* convertible to a
88
- // pointer-to-pointer, so the first overload of
89
- // check_type() is not a match.
90
- // However, an array IS convertible to a pointer,
91
- // and a pointer-to-array already is a pointer.
92
- // Any pointer is convertible to a void*,
93
- // so the second function overload is a match.
94
- // That overload returns a complete type (Is_array).
95
- // Because it's a complete type,
96
- // sizeof(Is_array) is a valid expression.
97
- // Thus, the compiler has EXCLUDED every possible type
98
- // except arrays via compilation errors before reaching
99
- // the third line.
100
- // Moreover, check1 and check2 are reduced to the value zero,
101
- // while the third line is the old type-unsafe C-style macro,
102
- // now made entirely type-safe.
103
- //
104
- // Additional benefits:
105
- // The result is itself constexpr
106
- //
107
- //
108
- #define ARRAY_SIZE2 (arr ) ( \
109
- 0 * sizeof (reinterpret_cast <const ::Bad_arg_to_COUNTOF*>(arr)) + /* check1*/ \
110
- 0 * sizeof (::Bad_arg_to_COUNTOF::check_type((arr), &(arr))) + /* check2*/ \
111
- sizeof (arr) / sizeof ((arr)[0 ]) /* eval */ \
112
- )
113
-
114
- struct Bad_arg_to_COUNTOF {
115
- class Is_pointer ; // incomplete
116
- class Is_array {};
117
- template <typename T>
118
- static Is_pointer check_type (const T*, const T* const *);
119
- static Is_array check_type (const void *, const void *);
120
- };
121
-
122
- #elif __cplusplus >= 201103L || /* any compiler claiming C++11 support */ \
123
- _MSC_VER >= 1900 || /* Visual C++ 2015 or higher */ \
124
- __has_feature (cxx_constexpr) /* CLang versions supporting constexp */
125
-
126
- #pragma message " C++11 version ARRAY_SIZE2"
127
-
128
- namespace detail
129
- {
130
- template <typename T, std::size_t N>
131
- constexpr std::size_t countof (T const (&)[N]) noexcept
132
- {
133
- return N;
134
- }
135
- } // namespace detail
136
- #define ARRAY_SIZE2 (arr ) detail::countof(arr)
137
-
138
- #elif _MSC_VER // Visual C++ fallback
139
-
140
- #pragma message "using Microsoft Visual C++ intrinsic ARRAY_SIZE2"
141
- #define ARRAY_SIZE2 (arr ) _countof(arr)
142
-
143
- #elif __cplusplus >= 199711L && ( /* C++ 98 trick */ \
144
- defined (__INTEL_COMPILER) || \
145
- defined(__clang__) || \
146
- (defined(__GNUC__) && ( \
147
- (__GNUC__ > 4 ) || \
148
- (__GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) \
149
- )))
150
-
151
- #pragma message " C++98 version ARRAY_SIZE2"
152
-
153
- template <typename T, std::size_t N>
154
- char (&_ArraySizeHelperRequiresArray (T(&)[N]))[N];
155
- #define ARRAY_SIZE2 (x ) sizeof (_ArraySizeHelperRequiresArray(x))
156
-
157
- #else
158
-
159
- #pragma message "Using type-unsafe version of ARRAY_SIZE2"
160
- // This is the worst-case scenario macro.
161
- // While it is valid C, it is NOT typesafe.
162
- // For example, if the parameter arr is a pointer instead of array,
163
- // the compiler will SILENTLY give a (likely) incorrect result.
164
- #define ARRAY_SIZE2 (arr ) sizeof (arr) / sizeof (arr[0 ])
165
-
166
- #endif
167
-
168
-
169
- #endif // ARRAYSIZE2_H
170
-
171
-
172
29
#ifndef COMPILE_DATE_H
173
30
#define COMPILE_DATE_H
174
31
0 commit comments