Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <type_traits>
- #include <utility>
- namespace equals_details {
- template<typename... Args>
- constexpr bool equals(Args&&...);
- template<typename T, typename U>
- constexpr bool equals(T&& lhs, U&& rhs) noexcept(noexcept(std::forward<T>(lhs) == std::forward<U>(rhs))) {
- return std::forward<T>(lhs) == std::forward<U>(rhs);
- }
- template<typename T, typename U, typename... Args>
- constexpr bool equals(T&& lhs, U&& rhs, Args&&... args)
- noexcept(noexcept(std::forward<T>(lhs) == std::forward<U>(rhs)) &&
- noexcept(equals(std::forward<U>(rhs), std::forward<Args>(args)...))) {
- return std::forward<T>(lhs) == std::forward<U>(rhs) &&
- equals(std::forward<T>(lhs), std::forward<Args>(args)...);
- }
- }
- // some information:
- // doesn't participate in overload resolution if (sizeof...(Args) < 2)
- // return: (a1 == a2 && a2 == a3 && ... && a(n - 1) == a(n)), where n = sizeof...(Args)
- // exceptions: noexcept(false) if any comparasion yields noexcept(false)
- template<typename... Args>
- constexpr auto equals(Args&&... args) -> std::enable_if_t<sizeof...(Args) >= 2, bool> {
- return equals_details::equals(std::forward<Args>(args)...);
- }
- #include <cassert>
- #include <string>
- namespace tests {
- // compile-time tests
- static_assert(equals(5, 5, 5), "expression (5 == 5 && 5 == 5) yields false");
- static_assert(!equals(5, 7, 1), "expression (5 == 7 && 7 == 1) yields true");
- void check_comparasion_count() {
- struct ComparasionCounter {
- unsigned& counter;
- bool operator==(const ComparasionCounter&) noexcept {
- ++counter;
- return true;
- }
- };
- unsigned counter = 0;
- ComparasionCounter a{counter}, b{counter}, c{counter};
- // equivalent to (a == b && b == c) -> 2 comparasions
- equals(a, b, c);
- assert(counter == 2);
- }
- void check_result() {
- using namespace std::string_literals;
- bool result1 = equals("_", "_"s, "_");
- bool result2 = equals("this"s, "is"s, "false"s);
- bool result3 = equals(54, 54.0, 54.0F, 54LL);
- //bool result4 = equals("H", 'H'); // ill-formed => there's no such comparasion (const char* == char)
- assert(result1 == true);
- assert(result2 == false);
- assert(result3 == true);
- }
- void noexcept_test() {
- using namespace std::string_literals;
- bool result1 = noexcept(equals(2, 5, 7));
- bool result2 = noexcept(equals("a"s, "d"));
- assert(result1 == true);
- assert(result2 == false);
- }
- }
- int main() {
- tests::check_comparasion_count();
- tests::check_result();
- tests::noexcept_test();
- }
Add Comment
Please, Sign In to add comment