Permalink
Browse files

Merge pull request #697

Add operator< for variant
  • Loading branch information...
Neverlord committed May 18, 2018
2 parents 640a55e + 82facf6 commit dd215eda32214754deed7ec61b74413084338228
Showing with 77 additions and 4 deletions.
  1. +57 −4 libcaf_core/caf/variant.hpp
  2. +20 −0 libcaf_core/test/variant.cpp
@@ -18,6 +18,7 @@
#pragma once
+#include <functional>
#include <type_traits>
#include "caf/config.hpp"
@@ -417,7 +418,7 @@ bool holds_alternative(const variant<Ts...>& data) {
}
/// @relates variant
-template <class T>
+template <class T, template <class> class Predicate>
struct variant_compare_helper {
using result_type = bool;
const T& lhs;
@@ -427,21 +428,21 @@ struct variant_compare_helper {
template <class U>
bool operator()(const U& rhs) const {
auto ptr = get_if<U>(&lhs);
- return ptr ? *ptr == rhs : false;
+ return ptr && Predicate<U>{}(*ptr, rhs);
}
};
/// @relates variant
template <class... Ts>
bool operator==(const variant<Ts...>& x, const variant<Ts...>& y) {
- variant_compare_helper<variant<Ts...>> f{x};
+ variant_compare_helper<variant<Ts...>, std::equal_to> f{x};
return visit(f, y);
}
/// @relates variant
template <class T, class... Ts>
bool operator==(const T& x, const variant<Ts...>& y) {
- variant_compare_helper<variant<Ts...>> f{y};
+ variant_compare_helper<variant<Ts...>, std::equal_to> f{y};
return f(x);
}
@@ -451,6 +452,58 @@ bool operator==(const variant<Ts...>& x, const T& y) {
return y == x;
}
+/// @relates variant
+template <class... Ts>
+bool operator<(const variant<Ts...>& x, const variant<Ts...>& y) {
+ if (y.valueless_by_exception())
+ return false;
+ if (x.valueless_by_exception())
+ return true;
+ if (x.index() != y.index())
+ return x.index() < y.index();
+ variant_compare_helper<variant<Ts...>, std::less> f{x};
+ return visit(f, y);
+}
+
+/// @relates variant
+template <class... Ts>
+bool operator>(const variant<Ts...>& x, const variant<Ts...>& y) {
+ if (x.valueless_by_exception())
+ return false;
+ if (y.valueless_by_exception())
+ return true;
+ if (x.index() != y.index())
+ return x.index() > y.index();
+ variant_compare_helper<variant<Ts...>, std::greater> f{x};
+ return visit(f, y);
+}
+
+/// @relates variant
+template <class... Ts>
+bool operator<=(const variant<Ts...>& x, const variant<Ts...>& y) {
+ if (x.valueless_by_exception())
+ return true;
+ if (y.valueless_by_exception())
+ return false;
+ if (x.index() != y.index())
+ return x.index() < y.index();
+ variant_compare_helper<variant<Ts...>, std::less_equal> f{x};
+ return visit(f, y);
+}
+
+/// @relates variant
+template <class... Ts>
+bool operator>=(const variant<Ts...>& x, const variant<Ts...>& y) {
+ if (y.valueless_by_exception())
+ return true;
+ if (x.valueless_by_exception())
+ return false;
+ if (x.index() != y.index())
+ return x.index() >= y.index();
+ variant_compare_helper<variant<Ts...>, std::greater_equal> f{x};
+ return visit(f, y);
+}
+
/// @relates variant
template <class T>
struct variant_reader {
@@ -149,3 +149,23 @@ CAF_TEST(n_ary_visit) {
CAF_CHECK_EQUAL(visit(f, a, b, c, d), "(42, 'foo', \"bar\", 123)");
}
+CAF_TEST(less_than) {
+ using variant_type = variant<char, int>;
+ auto a = variant_type{'x'};
+ auto b = variant_type{'y'};
+ CAF_CHECK(a < b);
+ CAF_CHECK(!(a > b));
+ CAF_CHECK(a <= b);
+ CAF_CHECK(!(a >= b));
+ b = 42;
+ CAF_CHECK(a < b);
+ CAF_CHECK(!(a > b));
+ CAF_CHECK(a <= b);
+ CAF_CHECK(!(a >= b));
+ a = 42;
+ CAF_CHECK(!(a < b));
+ CAF_CHECK(!(a > b));
+ CAF_CHECK(a <= b);
+ CAF_CHECK(a >= b);
+ b = 'x';
+}

0 comments on commit dd215ed

Please sign in to comment.