TemplateLib.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. * Reusable template meta-functions on types and compile-time values. Meta-
  7. * functions are placed inside the 'tl' namespace to avoid conflict with non-
  8. * meta functions of the same name (e.g., mozilla::tl::FloorLog2 vs.
  9. * mozilla::FloorLog2).
  10. *
  11. * When constexpr support becomes universal, we should probably use that instead
  12. * of some of these templates, for simplicity.
  13. */
  14. #ifndef mozilla_TemplateLib_h
  15. #define mozilla_TemplateLib_h
  16. #include <limits.h>
  17. #include <stddef.h>
  18. #include "mozilla/TypeTraits.h"
  19. namespace mozilla {
  20. namespace tl {
  21. /** Compute min/max. */
  22. template<size_t I, size_t J>
  23. struct Min
  24. {
  25. static const size_t value = I < J ? I : J;
  26. };
  27. template<size_t I, size_t J>
  28. struct Max
  29. {
  30. static const size_t value = I > J ? I : J;
  31. };
  32. /** Compute floor(log2(i)). */
  33. template<size_t I>
  34. struct FloorLog2
  35. {
  36. static const size_t value = 1 + FloorLog2<I / 2>::value;
  37. };
  38. template<> struct FloorLog2<0> { /* Error */ };
  39. template<> struct FloorLog2<1> { static const size_t value = 0; };
  40. /** Compute ceiling(log2(i)). */
  41. template<size_t I>
  42. struct CeilingLog2
  43. {
  44. static const size_t value = FloorLog2<2 * I - 1>::value;
  45. };
  46. /** Round up to the nearest power of 2. */
  47. template<size_t I>
  48. struct RoundUpPow2
  49. {
  50. static const size_t value = size_t(1) << CeilingLog2<I>::value;
  51. };
  52. template<>
  53. struct RoundUpPow2<0>
  54. {
  55. static const size_t value = 1;
  56. };
  57. /** Compute the number of bits in the given unsigned type. */
  58. template<typename T>
  59. struct BitSize
  60. {
  61. static const size_t value = sizeof(T) * CHAR_BIT;
  62. };
  63. /**
  64. * Produce an N-bit mask, where N <= BitSize<size_t>::value. Handle the
  65. * language-undefined edge case when N = BitSize<size_t>::value.
  66. */
  67. template<size_t N>
  68. struct NBitMask
  69. {
  70. // Assert the precondition. On success this evaluates to 0. Otherwise it
  71. // triggers divide-by-zero at compile time: a guaranteed compile error in
  72. // C++11, and usually one in C++98. Add this value to |value| to assure
  73. // its computation.
  74. static const size_t checkPrecondition =
  75. 0 / size_t(N < BitSize<size_t>::value);
  76. static const size_t value = (size_t(1) << N) - 1 + checkPrecondition;
  77. };
  78. template<>
  79. struct NBitMask<BitSize<size_t>::value>
  80. {
  81. static const size_t value = size_t(-1);
  82. };
  83. /**
  84. * For the unsigned integral type size_t, compute a mask M for N such that
  85. * for all X, !(X & M) implies X * N will not overflow (w.r.t size_t)
  86. */
  87. template<size_t N>
  88. struct MulOverflowMask
  89. {
  90. static const size_t value =
  91. ~NBitMask<BitSize<size_t>::value - CeilingLog2<N>::value>::value;
  92. };
  93. template<> struct MulOverflowMask<0> { /* Error */ };
  94. template<> struct MulOverflowMask<1> { static const size_t value = 0; };
  95. /**
  96. * And<bool...> computes the logical 'and' of its argument booleans.
  97. *
  98. * Examples:
  99. * mozilla::t1::And<true, true>::value is true.
  100. * mozilla::t1::And<true, false>::value is false.
  101. * mozilla::t1::And<>::value is true.
  102. */
  103. template<bool...>
  104. struct And;
  105. template<>
  106. struct And<> : public TrueType { };
  107. template<bool C1, bool... Cn>
  108. struct And<C1, Cn...>
  109. : public Conditional<C1, And<Cn...>, FalseType>::Type { };
  110. } // namespace tl
  111. } // namespace mozilla
  112. #endif /* mozilla_TemplateLib_h */