utility.h 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #pragma once
  2. #include "typetraits.h"
  3. #include <util/system/compiler.h>
  4. #include <cstring>
  5. template <class T>
  6. static constexpr const T& Min(const T& l Y_LIFETIME_BOUND, const T& r Y_LIFETIME_BOUND) {
  7. return r < l ? r : l;
  8. }
  9. template <typename T, typename... Args>
  10. static constexpr const T& Min(const T& a Y_LIFETIME_BOUND, const T& b Y_LIFETIME_BOUND, const Args&... args Y_LIFETIME_BOUND) {
  11. return Min(a, Min(b, args...));
  12. }
  13. template <class T>
  14. static constexpr const T& Max(const T& l Y_LIFETIME_BOUND, const T& r Y_LIFETIME_BOUND) {
  15. return l < r ? r : l;
  16. }
  17. template <typename T, typename... Args>
  18. static constexpr const T& Max(const T& a Y_LIFETIME_BOUND, const T& b Y_LIFETIME_BOUND, const Args&... args Y_LIFETIME_BOUND) {
  19. return Max(a, Max(b, args...));
  20. }
  21. // replace with http://en.cppreference.com/w/cpp/algorithm/clamp in c++17
  22. template <class T>
  23. constexpr const T& ClampVal(const T& val Y_LIFETIME_BOUND, const T& min Y_LIFETIME_BOUND, const T& max Y_LIFETIME_BOUND) {
  24. return val < min ? min : (max < val ? max : val);
  25. }
  26. template <typename T = double, typename... Args>
  27. static T Mean(const Args&... other) noexcept {
  28. const auto numArgs = sizeof...(other);
  29. auto sum = T();
  30. for (const auto& v : {other...}) {
  31. sum += v;
  32. }
  33. return sum / numArgs;
  34. }
  35. template <class T>
  36. static inline void Zero(T& t) noexcept {
  37. memset((void*)&t, 0, sizeof(t));
  38. }
  39. /**
  40. * Securely zero memory (compiler does not optimize this out)
  41. *
  42. * @param pointer void pointer to start of memory block to be zeroed
  43. * @param count size of memory block to be zeroed (in bytes)
  44. */
  45. void SecureZero(void* pointer, size_t count) noexcept;
  46. /**
  47. * Securely zero memory of given object (compiler does not optimize this out)
  48. *
  49. * @param t reference to object, which must be zeroed
  50. */
  51. template <class T>
  52. static inline void SecureZero(T& t) noexcept {
  53. SecureZero((void*)&t, sizeof(t));
  54. }
  55. namespace NSwapCheck {
  56. Y_HAS_MEMBER(swap);
  57. Y_HAS_MEMBER(Swap);
  58. template <class T, class = void>
  59. struct TSwapSelector {
  60. static inline void Swap(T& l, T& r) noexcept(std::is_nothrow_move_constructible<T>::value &&
  61. std::is_nothrow_move_assignable<T>::value) {
  62. T tmp(std::move(l));
  63. l = std::move(r);
  64. r = std::move(tmp);
  65. }
  66. };
  67. template <class T>
  68. struct TSwapSelector<T, std::enable_if_t<THasSwap<T>::value>> {
  69. static inline void Swap(T& l, T& r) noexcept(noexcept(l.Swap(r))) {
  70. l.Swap(r);
  71. }
  72. };
  73. template <class T>
  74. struct TSwapSelector<T, std::enable_if_t<THasswap<T>::value && !THasSwap<T>::value>> {
  75. static inline void Swap(T& l, T& r) noexcept(noexcept(l.swap(r))) {
  76. l.swap(r);
  77. }
  78. };
  79. } // namespace NSwapCheck
  80. /*
  81. * DoSwap better than ::Swap in member functions...
  82. */
  83. template <class T>
  84. static inline void DoSwap(T& l, T& r) noexcept(noexcept(NSwapCheck::TSwapSelector<T>::Swap(l, r))) {
  85. NSwapCheck::TSwapSelector<T>::Swap(l, r);
  86. }
  87. template <bool b>
  88. struct TNullTmpl {
  89. template <class T>
  90. operator T() const {
  91. return (T)0;
  92. }
  93. };
  94. using TNull = TNullTmpl<0>;
  95. /*
  96. * Class for zero-initialize padding bytes in derived classes
  97. */
  98. template <typename TDerived>
  99. class TZeroInit {
  100. protected:
  101. TZeroInit() {
  102. // Actually, safe because this as TDerived is not initialized yet.
  103. Zero(*static_cast<TDerived*>(this));
  104. }
  105. };
  106. struct TIdentity {
  107. template <class T>
  108. constexpr decltype(auto) operator()(T&& x) const noexcept {
  109. return std::forward<T>(x);
  110. }
  111. };