utility.h 3.3 KB

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