Commit 08f76548 authored by Matthias Vallentin's avatar Matthias Vallentin

Make optional<T> totally ordered

This change adds the necessary operator overloads to make optional<T>
totally ordered, per the current draft of the standard. As reference
serves the implementation of libstdc++ version 5.3. As CAF doesn't have
nullopt_t, we use none_t.
parent 2b4f8c8b
......@@ -258,69 +258,193 @@ serialize(Processor& source, optional<T>& x, const unsigned int) {
x = none;
}
// -- [X.Y.8] comparison with optional ----------------------------------------
/// @relates optional
template <class T, class U>
bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
if (lhs)
return rhs ? detail::safe_equal(*lhs, *rhs) : false;
return ! rhs;
template <class T>
bool operator==(const optional<T>& lhs, const optional<T>& rhs) {
return static_cast<bool>(lhs) == static_cast<bool>(rhs)
&& (! lhs || *lhs == *rhs);
}
/// @relates optional
template <class T, class U>
bool operator==(const optional<T>& lhs, const U& rhs) {
return (lhs) ? *lhs == rhs : false;
template <class T>
bool operator!=(const optional<T>& lhs, const optional<T>& rhs) {
return ! (lhs == rhs);
}
/// @relates optional
template <class T, class U>
bool operator==(const T& lhs, const optional<U>& rhs) {
return rhs == lhs;
template <class T>
bool operator<(const optional<T>& lhs, const optional<T>& rhs) {
return static_cast<bool>(rhs) && (! lhs || *lhs < *rhs);
}
/// @relates optional
template <class T, class U>
bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
return ! (lhs == rhs);
template <class T>
bool operator<=(const optional<T>& lhs, const optional<T>& rhs) {
return ! (rhs < lhs);
}
/// @relates optional
template <class T, class U>
bool operator!=(const optional<T>& lhs, const U& rhs) {
return ! (lhs == rhs);
template <class T>
bool operator>=(const optional<T>& lhs, const optional<T>& rhs) {
return ! (lhs < rhs);
}
/// @relates optional
template <class T, class U>
bool operator!=(const T& lhs, const optional<U>& rhs) {
return ! (lhs == rhs);
template <class T>
bool operator>(const optional<T>& lhs, const optional<T>& rhs) {
return rhs < lhs;
}
// -- [X.Y.9] comparison with none_t (aka. nullopt_t) -------------------------
/// @relates optional
template <class T, class U>
bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
// none is considered smaller than any actual value
if (lhs)
return rhs ? *lhs < *rhs : false;
template <class T>
bool operator==(const optional<T>& lhs, none_t) {
return ! lhs;
}
/// @relates optional
template <class T>
bool operator==(none_t, const optional<T>& rhs) {
return ! rhs;
}
/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, none_t) {
return static_cast<bool>(lhs);
}
/// @relates optional
template <class T>
bool operator!=(none_t, const optional<T>& rhs) {
return static_cast<bool>(rhs);
}
/// @relates optional
template <class T, class U>
bool operator<(const optional<T>& lhs, const U& rhs) {
if (lhs)
return *lhs < rhs;
template <class T>
bool operator<(const optional<T>&, none_t) {
return false;
}
/// @relates optional
template <class T>
bool operator<(none_t, const optional<T>& rhs) {
return static_cast<bool>(rhs);
}
/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, none_t) {
return ! lhs;
}
/// @relates optional
template <class T>
bool operator<=(none_t, const optional<T>&) {
return true;
}
/// @relates optional
template <class T, class U>
bool operator<(T& lhs, const optional<U>& rhs) {
if (rhs)
return lhs < *rhs;
template <class T>
bool operator>(const optional<T>& lhs, none_t) {
return static_cast<bool>(lhs);
}
/// @relates optional
template <class T>
bool operator>(none_t, const optional<T>&) {
return false;
}
/// @relates optional
template <class T>
bool operator>=(const optional<T>&, none_t) {
return true;
}
/// @relates optional
template <class T>
bool operator>=(none_t, const optional<T>&) {
return true;
}
// -- [X.Y.10] comparison with value type ------------------------------------
/// @relates optional
template <class T>
bool operator==(const optional<T>& lhs, const T& rhs) {
return lhs && *lhs == rhs;
}
/// @relates optional
template <class T>
bool operator==(const T& lhs, const optional<T>& rhs) {
return rhs && lhs == *rhs;
}
/// @relates optional
template <class T>
bool operator!=(const optional<T>& lhs, const T& rhs) {
return ! lhs || ! (*lhs == rhs);
}
/// @relates optional
template <class T>
bool operator!=(const T& lhs, const optional<T>& rhs) {
return ! rhs || ! (lhs == *rhs);
}
/// @relates optional
template <class T>
bool operator<(const optional<T>& lhs, const T& rhs) {
return ! lhs || *lhs < rhs;
}
/// @relates optional
template <class T>
bool operator<(const T& lhs, const optional<T>& rhs) {
return rhs && lhs < *rhs;
}
/// @relates optional
template <class T>
bool operator<=(const optional<T>& lhs, const T& rhs) {
return ! lhs || ! (rhs < *lhs);
}
/// @relates optional
template <class T>
bool operator<=(const T& lhs, const optional<T>& rhs) {
return rhs && ! (rhs < lhs);
}
/// @relates optional
template <class T>
bool operator>(const optional<T>& lhs, const T& rhs) {
return lhs && rhs < *lhs;
}
/// @relates optional
template <class T>
bool operator>(const T& lhs, const optional<T>& rhs) {
return ! rhs || *rhs < lhs;
}
/// @relates optional
template <class T>
bool operator>=(const optional<T>& lhs, const T& rhs) {
return lhs && ! (*lhs < rhs);
}
/// @relates optional
template <class T>
bool operator>=(const T& lhs, const optional<T>& rhs) {
return ! rhs || ! (lhs < *rhs);
}
} // namespace caf
#endif // CAF_OPTIONAL_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2016 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE optional
#include "caf/test/unit_test.hpp"
#include "caf/optional.hpp"
using namespace std;
using namespace caf;
namespace {
struct qwertz {
qwertz(int x, int y) : x_(x), y_(y) {
// nop
}
int x_;
int y_;
};
bool operator==(const qwertz& lhs, const qwertz& rhs) {
return lhs.x_ == rhs.x_ && lhs.y_ == rhs.y_;
}
} // namespace <anonymous>
CAF_TEST(empty) {
optional<int> x;
optional<int> y;
CAF_CHECK(x == y);
CAF_CHECK(!(x != y));
}
CAF_TEST(equality) {
optional<int> x = 42;
optional<int> y = 7;
CAF_CHECK(x != y);
CAF_CHECK(!(x == y));
}
CAF_TEST(ordering) {
optional<int> x = 42;
optional<int> y = 7;
CAF_CHECK(x > y);
CAF_CHECK(x >= y);
CAF_CHECK(y < x);
CAF_CHECK(y <= x);
CAF_CHECK(!(y > x));
CAF_CHECK(!(y >= x));
CAF_CHECK(!(x < y));
CAF_CHECK(!(x <= y));
CAF_CHECK(x < 4711);
CAF_CHECK(4711 > x);
CAF_CHECK(4711 >= x);
CAF_CHECK(!(x > 4711));
CAF_CHECK(!(x >= 4711));
CAF_CHECK(!(4211 < x));
CAF_CHECK(!(4211 <= x));
}
CAF_TEST(custom_type_none) {
optional<qwertz> x;
CAF_CHECK(x == none);
}
CAF_TEST(custom_type_engaged) {
qwertz obj{1, 2};
optional<qwertz> x = obj;
CAF_CHECK(x != none);
CAF_CHECK(obj == x);
CAF_CHECK(x == obj );
CAF_CHECK(obj == *x);
CAF_CHECK(*x == obj);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment