Radfler

::equals (+tests)

Apr 9th, 2016
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.53 KB | None | 0 0
  1. #include <type_traits>
  2. #include <utility>
  3.  
  4. namespace equals_details {
  5.  
  6.     template<typename... Args>
  7.     constexpr bool equals(Args&&...);
  8.  
  9.     template<typename T, typename U>
  10.     constexpr bool equals(T&& lhs, U&& rhs) noexcept(noexcept(std::forward<T>(lhs) == std::forward<U>(rhs))) {
  11.         return std::forward<T>(lhs) == std::forward<U>(rhs);
  12.     }
  13.  
  14.     template<typename T, typename U, typename... Args>
  15.     constexpr bool equals(T&& lhs, U&& rhs, Args&&... args)
  16.  
  17.         noexcept(noexcept(std::forward<T>(lhs) == std::forward<U>(rhs)) &&
  18.                  noexcept(equals(std::forward<U>(rhs), std::forward<Args>(args)...))) {
  19.  
  20.         return std::forward<T>(lhs) == std::forward<U>(rhs) &&
  21.             equals(std::forward<T>(lhs), std::forward<Args>(args)...);
  22.  
  23.     }
  24.  
  25. }
  26.  
  27. // some information:
  28. // doesn't participate in overload resolution if (sizeof...(Args) < 2)
  29. // return: (a1 == a2 && a2 == a3 && ... && a(n - 1) == a(n)), where n = sizeof...(Args)
  30. // exceptions: noexcept(false) if any comparasion yields noexcept(false)
  31.  
  32. template<typename... Args>
  33. constexpr auto equals(Args&&... args) -> std::enable_if_t<sizeof...(Args) >= 2, bool> {
  34.  
  35.     return equals_details::equals(std::forward<Args>(args)...);
  36.  
  37. }
  38.  
  39. #include <cassert>
  40. #include <string>
  41.  
  42. namespace tests {
  43.  
  44.     // compile-time tests
  45.     static_assert(equals(5, 5, 5), "expression (5 == 5 && 5 == 5) yields false");
  46.     static_assert(!equals(5, 7, 1), "expression (5 == 7 && 7 == 1) yields true");
  47.  
  48.     void check_comparasion_count() {
  49.  
  50.         struct ComparasionCounter {
  51.  
  52.             unsigned& counter;
  53.  
  54.             bool operator==(const ComparasionCounter&) noexcept {
  55.                 ++counter;
  56.                 return true;
  57.             }
  58.  
  59.         };
  60.  
  61.         unsigned counter = 0;
  62.         ComparasionCounter a{counter}, b{counter}, c{counter};
  63.  
  64.         // equivalent to (a == b && b == c) -> 2 comparasions
  65.         equals(a, b, c);
  66.  
  67.         assert(counter == 2);
  68.  
  69.     }
  70.  
  71.     void check_result() {
  72.  
  73.         using namespace std::string_literals;
  74.  
  75.         bool result1 = equals("_", "_"s, "_");
  76.         bool result2 = equals("this"s, "is"s, "false"s);
  77.         bool result3 = equals(54, 54.0, 54.0F, 54LL);
  78.         //bool result4 = equals("H", 'H'); // ill-formed => there's no such comparasion (const char* == char)
  79.  
  80.         assert(result1 == true);
  81.         assert(result2 == false);
  82.         assert(result3 == true);
  83.  
  84.     }
  85.  
  86.     void noexcept_test() {
  87.  
  88.         using namespace std::string_literals;
  89.  
  90.         bool result1 = noexcept(equals(2, 5, 7));
  91.         bool result2 = noexcept(equals("a"s, "d"));
  92.  
  93.         assert(result1 == true);
  94.         assert(result2 == false);
  95.  
  96.     }
  97.  
  98. }
  99.  
  100. int main() {
  101.  
  102.     tests::check_comparasion_count();
  103.     tests::check_result();
  104.     tests::noexcept_test();
  105.  
  106. }
Add Comment
Please, Sign In to add comment