Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
templates.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_UTIL_TEMPLATES_HPP_INCLUDED 00006 #define UAVCAN_UTIL_TEMPLATES_HPP_INCLUDED 00007 00008 #include <climits> 00009 #include <cstddef> 00010 #include <cmath> 00011 #include <uavcan/build_config.hpp> 00012 00013 #ifndef UAVCAN_CPP_VERSION 00014 # error UAVCAN_CPP_VERSION 00015 #endif 00016 #if UAVCAN_CPP_VERSION < UAVCAN_CPP11 00017 # include <float.h> // cfloat may not be available 00018 #else 00019 # include <cfloat> // C++11 mode assumes that all standard headers are available 00020 #endif 00021 00022 namespace uavcan 00023 { 00024 /** 00025 * Usage: 00026 * StaticAssert<expression>::check(); 00027 */ 00028 template <bool Value> 00029 struct UAVCAN_EXPORT StaticAssert; 00030 00031 template <> 00032 struct UAVCAN_EXPORT StaticAssert<true> 00033 { 00034 static void check() { } 00035 }; 00036 00037 /** 00038 * Usage: 00039 * ShowIntegerAsError<integer_expression>::foobar(); 00040 */ 00041 template <long N> struct ShowIntegerAsError; 00042 00043 /** 00044 * Prevents copying when inherited 00045 */ 00046 class UAVCAN_EXPORT Noncopyable 00047 { 00048 Noncopyable(const Noncopyable&); 00049 Noncopyable& operator=(const Noncopyable&); 00050 protected: 00051 Noncopyable() { } 00052 ~Noncopyable() { } 00053 }; 00054 00055 /** 00056 * Compile time conditions 00057 */ 00058 template <bool B, typename T = void> 00059 struct UAVCAN_EXPORT EnableIf { }; 00060 00061 template <typename T> 00062 struct UAVCAN_EXPORT EnableIf<true, T> 00063 { 00064 typedef T Type; 00065 }; 00066 00067 /** 00068 * Lightweight type categorization. 00069 */ 00070 template <typename T, typename R = void> 00071 struct UAVCAN_EXPORT EnableIfType 00072 { 00073 typedef R Type; 00074 }; 00075 00076 /** 00077 * Compile-time type selection (Alexandrescu) 00078 */ 00079 template <bool Condition, typename TrueType, typename FalseType> 00080 struct UAVCAN_EXPORT Select; 00081 00082 template <typename TrueType, typename FalseType> 00083 struct UAVCAN_EXPORT Select<true, TrueType, FalseType> 00084 { 00085 typedef TrueType Result; 00086 }; 00087 00088 template <typename TrueType, typename FalseType> 00089 struct UAVCAN_EXPORT Select<false, TrueType, FalseType> 00090 { 00091 typedef FalseType Result; 00092 }; 00093 00094 /** 00095 * Checks if two identifiers refer to the same type. 00096 */ 00097 template<class T, class U> 00098 struct IsSameType 00099 { 00100 enum { Result = 0 }; 00101 }; 00102 00103 template <typename T> 00104 struct IsSameType<T, T> 00105 { 00106 enum { Result = 1 }; 00107 }; 00108 00109 /** 00110 * Remove reference as in <type_traits> 00111 */ 00112 template <typename T> struct RemoveReference { typedef T Type; }; 00113 template <typename T> struct RemoveReference<T&> { typedef T Type; }; 00114 #if UAVCAN_CPP_VERSION > UAVCAN_CPP03 00115 template <typename T> struct RemoveReference<T&&> { typedef T Type; }; 00116 #endif 00117 00118 /** 00119 * Parameter types 00120 */ 00121 template <typename U> struct ParameterType { typedef const U& Type; }; 00122 template <typename U> struct ParameterType<U&> { typedef U& Type; }; 00123 #if UAVCAN_CPP_VERSION > UAVCAN_CPP03 00124 template <typename U> struct ParameterType<U&&> { typedef U&& Type; }; 00125 #endif 00126 00127 /** 00128 * Value types 00129 */ 00130 template <bool> struct UAVCAN_EXPORT BooleanType { }; 00131 typedef BooleanType<true> TrueType; 00132 typedef BooleanType<false> FalseType; 00133 00134 template <int N> struct IntToType { }; 00135 00136 /** 00137 * Relations 00138 */ 00139 template <typename T1, typename T2> 00140 class UAVCAN_EXPORT IsImplicitlyConvertibleFromTo 00141 { 00142 template <typename U> static U returner(); 00143 00144 struct True_ { char x[2]; }; 00145 struct False_ { }; 00146 00147 static True_ test(const T2 &); 00148 static False_ test(...); 00149 00150 public: 00151 enum { Result = sizeof(True_) == sizeof(IsImplicitlyConvertibleFromTo<T1, T2>::test(returner<T1>())) }; 00152 }; 00153 00154 /** 00155 * coerceOrFallback<To>(From) 00156 * coerceOrFallback<To>(From, To) 00157 * @{ 00158 */ 00159 template <typename From, typename To> 00160 struct UAVCAN_EXPORT CoerceOrFallbackImpl 00161 { 00162 static To impl(const From& from, const To&, TrueType) { return To(from); } 00163 static To impl(const From&, const To& default_, FalseType) { return default_; } 00164 }; 00165 00166 /** 00167 * If possible, performs an implicit cast from the type From to the type To. 00168 * If the cast is not possible, returns default_ of type To. 00169 */ 00170 template <typename To, typename From> 00171 UAVCAN_EXPORT 00172 To coerceOrFallback(const From& from, const To& default_) 00173 { 00174 return CoerceOrFallbackImpl<From, To>::impl(from, default_, 00175 BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>()); 00176 } 00177 00178 /** 00179 * If possible, performs an implicit cast from the type From to the type To. 00180 * If the cast is not possible, returns a default constructed object of the type To. 00181 */ 00182 template <typename To, typename From> 00183 UAVCAN_EXPORT 00184 To coerceOrFallback(const From& from) 00185 { 00186 return CoerceOrFallbackImpl<From, To>::impl(from, To(), 00187 BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>()); 00188 } 00189 /** 00190 * @} 00191 */ 00192 00193 /** 00194 * Selects smaller value 00195 */ 00196 template <long A, long B> 00197 struct EnumMin 00198 { 00199 enum { Result = (A < B) ? A : B }; 00200 }; 00201 00202 /** 00203 * Selects larger value 00204 */ 00205 template <long A, long B> 00206 struct EnumMax 00207 { 00208 enum { Result = (A > B) ? A : B }; 00209 }; 00210 00211 /** 00212 * Compile time square root for integers. 00213 * Useful for operations on square matrices. 00214 */ 00215 template <unsigned Value> struct UAVCAN_EXPORT CompileTimeIntSqrt; 00216 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<1> { enum { Result = 1 }; }; 00217 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<4> { enum { Result = 2 }; }; 00218 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<9> { enum { Result = 3 }; }; 00219 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<16> { enum { Result = 4 }; }; 00220 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<25> { enum { Result = 5 }; }; 00221 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<36> { enum { Result = 6 }; }; 00222 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<49> { enum { Result = 7 }; }; 00223 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<64> { enum { Result = 8 }; }; 00224 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<81> { enum { Result = 9 }; }; 00225 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<100> { enum { Result = 10 }; }; 00226 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<121> { enum { Result = 11 }; }; 00227 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<144> { enum { Result = 12 }; }; 00228 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<169> { enum { Result = 13 }; }; 00229 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<196> { enum { Result = 14 }; }; 00230 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<225> { enum { Result = 15 }; }; 00231 template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<256> { enum { Result = 16 }; }; 00232 00233 /** 00234 * Replacement for std::copy(..) 00235 */ 00236 template <typename InputIt, typename OutputIt> 00237 UAVCAN_EXPORT 00238 OutputIt copy(InputIt first, InputIt last, OutputIt result) 00239 { 00240 while (first != last) 00241 { 00242 *result = *first; 00243 ++first; 00244 ++result; 00245 } 00246 return result; 00247 } 00248 00249 /** 00250 * Replacement for std::fill(..) 00251 */ 00252 template <typename ForwardIt, typename T> 00253 UAVCAN_EXPORT 00254 void fill(ForwardIt first, ForwardIt last, const T& value) 00255 { 00256 while (first != last) 00257 { 00258 *first = value; 00259 ++first; 00260 } 00261 } 00262 00263 /** 00264 * Replacement for std::fill_n(..) 00265 */ 00266 template<typename OutputIt, typename T> 00267 UAVCAN_EXPORT 00268 void fill_n(OutputIt first, std::size_t n, const T& value) 00269 { 00270 while (n--) 00271 { 00272 *first++ = value; 00273 } 00274 } 00275 00276 /** 00277 * Replacement for std::min(..) 00278 */ 00279 template <typename T> 00280 UAVCAN_EXPORT 00281 const T& min(const T& a, const T& b) 00282 { 00283 return (b < a) ? b : a; 00284 } 00285 00286 /** 00287 * Replacement for std::max(..) 00288 */ 00289 template <typename T> 00290 UAVCAN_EXPORT 00291 const T& max(const T& a, const T& b) 00292 { 00293 return (a < b) ? b : a; 00294 } 00295 00296 /** 00297 * Replacement for std::lexicographical_compare(..) 00298 */ 00299 template<typename InputIt1, typename InputIt2> 00300 UAVCAN_EXPORT 00301 bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) 00302 { 00303 while ((first1 != last1) && (first2 != last2)) 00304 { 00305 if (*first1 < *first2) 00306 { 00307 return true; 00308 } 00309 if (*first2 < *first1) 00310 { 00311 return false; 00312 } 00313 ++first1; 00314 ++first2; 00315 } 00316 return (first1 == last1) && (first2 != last2); 00317 } 00318 00319 /** 00320 * Replacement for std::equal(..) 00321 */ 00322 template<typename InputIt1, typename InputIt2> 00323 UAVCAN_EXPORT 00324 bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) 00325 { 00326 while (first1 != last1) 00327 { 00328 if (*first1 != *first2) 00329 { 00330 return false; 00331 } 00332 ++first1; 00333 ++first2; 00334 } 00335 return true; 00336 } 00337 00338 /** 00339 * Numeric traits, like std::numeric_limits<> 00340 */ 00341 template <typename T> 00342 struct UAVCAN_EXPORT NumericTraits; 00343 00344 /// bool 00345 template <> 00346 struct UAVCAN_EXPORT NumericTraits<bool> 00347 { 00348 enum { IsSigned = 0 }; 00349 enum { IsInteger = 1 }; 00350 static bool max() { return true; } 00351 static bool min() { return false; } 00352 }; 00353 00354 /// char 00355 template <> 00356 struct UAVCAN_EXPORT NumericTraits<char> 00357 { 00358 enum { IsSigned = 1 }; 00359 enum { IsInteger = 1 }; 00360 static char max() { return CHAR_MAX; } 00361 static char min() { return CHAR_MIN; } 00362 }; 00363 template <> 00364 struct UAVCAN_EXPORT NumericTraits<signed char> 00365 { 00366 enum { IsSigned = 1 }; 00367 enum { IsInteger = 1 }; 00368 static signed char max() { return SCHAR_MAX; } 00369 static signed char min() { return SCHAR_MIN; } 00370 }; 00371 template <> 00372 struct UAVCAN_EXPORT NumericTraits<unsigned char> 00373 { 00374 enum { IsSigned = 0 }; 00375 enum { IsInteger = 1 }; 00376 static unsigned char max() { return UCHAR_MAX; } 00377 static unsigned char min() { return 0; } 00378 }; 00379 00380 /// short 00381 template <> 00382 struct UAVCAN_EXPORT NumericTraits<short> 00383 { 00384 enum { IsSigned = 1 }; 00385 enum { IsInteger = 1 }; 00386 static short max() { return SHRT_MAX; } 00387 static short min() { return SHRT_MIN; } 00388 }; 00389 template <> 00390 struct UAVCAN_EXPORT NumericTraits<unsigned short> 00391 { 00392 enum { IsSigned = 0 }; 00393 enum { IsInteger = 1 }; 00394 static unsigned short max() { return USHRT_MAX; } 00395 static unsigned short min() { return 0; } 00396 }; 00397 00398 /// int 00399 template <> 00400 struct UAVCAN_EXPORT NumericTraits<int> 00401 { 00402 enum { IsSigned = 1 }; 00403 enum { IsInteger = 1 }; 00404 static int max() { return INT_MAX; } 00405 static int min() { return INT_MIN; } 00406 }; 00407 template <> 00408 struct UAVCAN_EXPORT NumericTraits<unsigned int> 00409 { 00410 enum { IsSigned = 0 }; 00411 enum { IsInteger = 1 }; 00412 static unsigned int max() { return UINT_MAX; } 00413 static unsigned int min() { return 0; } 00414 }; 00415 00416 /// long 00417 template <> 00418 struct UAVCAN_EXPORT NumericTraits<long> 00419 { 00420 enum { IsSigned = 1 }; 00421 enum { IsInteger = 1 }; 00422 static long max() { return LONG_MAX; } 00423 static long min() { return LONG_MIN; } 00424 }; 00425 template <> 00426 struct UAVCAN_EXPORT NumericTraits<unsigned long> 00427 { 00428 enum { IsSigned = 0 }; 00429 enum { IsInteger = 1 }; 00430 static unsigned long max() { return ULONG_MAX; } 00431 static unsigned long min() { return 0; } 00432 }; 00433 00434 /// long long 00435 template <> 00436 struct UAVCAN_EXPORT NumericTraits<long long> 00437 { 00438 enum { IsSigned = 1 }; 00439 enum { IsInteger = 1 }; 00440 static long long max() { return LLONG_MAX; } 00441 static long long min() { return LLONG_MIN; } 00442 }; 00443 template <> 00444 struct UAVCAN_EXPORT NumericTraits<unsigned long long> 00445 { 00446 enum { IsSigned = 0 }; 00447 enum { IsInteger = 1 }; 00448 static unsigned long long max() { return ULLONG_MAX; } 00449 static unsigned long long min() { return 0; } 00450 }; 00451 00452 /// float 00453 template <> 00454 struct UAVCAN_EXPORT NumericTraits<float> 00455 { 00456 enum { IsSigned = 1 }; 00457 enum { IsInteger = 0 }; 00458 static float max() { return FLT_MAX; } 00459 static float min() { return FLT_MIN; } 00460 static float infinity() { return INFINITY; } 00461 static float epsilon() { return FLT_EPSILON; } 00462 }; 00463 00464 /// double 00465 template <> 00466 struct UAVCAN_EXPORT NumericTraits<double> 00467 { 00468 enum { IsSigned = 1 }; 00469 enum { IsInteger = 0 }; 00470 static double max() { return DBL_MAX; } 00471 static double min() { return DBL_MIN; } 00472 static double infinity() { return static_cast<double>(INFINITY) * static_cast<double>(INFINITY); } 00473 static double epsilon() { return DBL_EPSILON; } 00474 }; 00475 00476 #if defined(LDBL_MAX) && defined(LDBL_MIN) && defined(LDBL_EPSILON) 00477 /// long double 00478 template <> 00479 struct UAVCAN_EXPORT NumericTraits<long double> 00480 { 00481 enum { IsSigned = 1 }; 00482 enum { IsInteger = 0 }; 00483 static long double max() { return LDBL_MAX; } 00484 static long double min() { return LDBL_MIN; } 00485 static long double infinity() { return static_cast<long double>(INFINITY) * static_cast<long double>(INFINITY); } 00486 static long double epsilon() { return LDBL_EPSILON; } 00487 }; 00488 #endif 00489 00490 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 00491 # undef isnan 00492 # undef isinf 00493 # undef signbit 00494 #endif 00495 00496 /** 00497 * Replacement for std::isnan(). 00498 * Note that direct float comparison (==, !=) is intentionally avoided. 00499 */ 00500 template <typename T> 00501 inline bool isNaN(T arg) 00502 { 00503 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 00504 return std::isnan(arg); 00505 #else 00506 // coverity[same_on_both_sides : FALSE] 00507 // cppcheck-suppress duplicateExpression 00508 return !(arg <= arg); 00509 #endif 00510 } 00511 00512 /** 00513 * Replacement for std::isinf(). 00514 * Note that direct float comparison (==, !=) is intentionally avoided. 00515 */ 00516 template <typename T> 00517 inline bool isInfinity(T arg) 00518 { 00519 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 00520 return std::isinf(arg); 00521 #else 00522 return (arg >= NumericTraits<T>::infinity()) || (arg <= -NumericTraits<T>::infinity()); 00523 #endif 00524 } 00525 00526 /** 00527 * Replacement for std::isfinite(). 00528 * Note that direct float comparison (==, !=) is intentionally avoided. 00529 */ 00530 template <typename T> 00531 inline bool isFinite(T arg) 00532 { 00533 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 00534 return std::isfinite(arg); 00535 #else 00536 return !isNaN(arg) && !isInfinity(arg); 00537 #endif 00538 } 00539 00540 /** 00541 * Replacement for std::signbit(). 00542 * Note that direct float comparison (==, !=) is intentionally avoided. 00543 */ 00544 template <typename T> 00545 inline bool getSignBit(T arg) 00546 { 00547 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 00548 return std::signbit(arg); 00549 #else 00550 // coverity[divide_by_zero : FALSE] 00551 return arg < T(0) || (((arg <= T(0)) && (arg >= T(0))) && (T(1) / arg < T(0))); 00552 #endif 00553 } 00554 00555 } 00556 00557 #endif // UAVCAN_UTIL_TEMPLATES_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:34 by
1.7.2