Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers templates.hpp Source File

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