2014-05-02 15:52:47 -07:00
|
|
|
#ifndef EINA_OPTIONAL_HH_
|
|
|
|
#define EINA_OPTIONAL_HH_
|
|
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <utility>
|
2015-01-05 09:35:49 -08:00
|
|
|
#include <type_traits>
|
2014-05-02 15:52:47 -07:00
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @addtogroup Eina_Cxx_Data_Types_Group
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2014-05-02 15:52:47 -07:00
|
|
|
namespace efl_eina_swap_adl {
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
void swap_impl(T& lhs, T& rhs)
|
|
|
|
{
|
|
|
|
using namespace std;
|
|
|
|
swap(lhs, rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace efl { namespace eina {
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @defgroup Eina_Cxx_Optional_Group Optional Value
|
|
|
|
* @ingroup Eina_Cxx_Data_Types_Group
|
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
void adl_swap(T& lhs, T& rhs)
|
|
|
|
{
|
|
|
|
::efl_eina_swap_adl::swap_impl<T>(lhs, rhs);
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* This class manages an optional contained value, i.e. a value that
|
|
|
|
* semantically may not be present.
|
|
|
|
*
|
|
|
|
* A common use case for optional is the return value of a function that
|
|
|
|
* may fail. As opposed to other approaches, such as
|
|
|
|
* <tt>std::pair<T,bool></tt>, optional handles expensive to construct
|
|
|
|
* objects well and is more readable, as the intent is expressed
|
|
|
|
* explicitly.
|
|
|
|
*
|
|
|
|
* An optional object holding a semantically present value is considered
|
|
|
|
* to be @em engaged, otherwise it is considered to be @em disengaged.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
struct optional
|
|
|
|
{
|
2014-06-04 13:34:42 -07:00
|
|
|
typedef optional<T> _self_type; /**< Type for the optional class itself. */
|
2014-05-02 15:52:47 -07:00
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Create a disengaged object.
|
|
|
|
*
|
|
|
|
* This constructor creates a disengaged <tt>eina::optional</tt>
|
2015-02-12 17:22:50 -08:00
|
|
|
* object.
|
2014-06-04 13:34:42 -07:00
|
|
|
*/
|
2015-02-12 17:22:50 -08:00
|
|
|
constexpr optional(std::nullptr_t) : engaged(false)
|
2014-05-02 15:52:47 -07:00
|
|
|
{}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Default constructor. Create a disengaged object.
|
|
|
|
*/
|
2015-02-12 17:22:50 -08:00
|
|
|
constexpr optional() : engaged(false)
|
2014-05-02 15:52:47 -07:00
|
|
|
{}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create an engaged object by moving @p other content.
|
|
|
|
* @param other R-value reference to the desired type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object in an
|
|
|
|
* engaged state. The contained value is initialized by moving
|
|
|
|
* @p other.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
optional(T&& other) : engaged(false)
|
|
|
|
{
|
2015-01-05 09:35:49 -08:00
|
|
|
_construct(std::forward<T>(other));
|
2014-05-02 15:52:47 -07:00
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create an engaged object by copying @p other content.
|
|
|
|
* @param other Constant reference to the desired type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object in an
|
|
|
|
* engaged state. The contained value is initialized by copying
|
|
|
|
* @p other.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
optional(T const& other) : engaged(false)
|
|
|
|
{
|
2015-01-05 09:35:49 -08:00
|
|
|
_construct(other);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create an engaged object by moving @p other content.
|
|
|
|
* @param other R-value reference to the desired type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object in an
|
|
|
|
* engaged state. The contained value is initialized by moving
|
|
|
|
* @p other.
|
|
|
|
*/
|
|
|
|
template <typename U>
|
|
|
|
optional(U&& other, typename std::enable_if<std::is_convertible<U, T>::value>::type* = 0) : engaged(false)
|
|
|
|
{
|
|
|
|
_construct(std::forward<U>(other));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create an engaged object by copying @p other content.
|
|
|
|
* @param other Constant reference to the desired type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object in an
|
|
|
|
* engaged state. The contained value is initialized by copying
|
|
|
|
* @p other.
|
|
|
|
*/
|
|
|
|
template <typename U>
|
|
|
|
optional(U const& other, typename std::enable_if<std::is_convertible<U, T>::value>::type* = 0) : engaged(false)
|
|
|
|
{
|
|
|
|
_construct(other);
|
2014-05-02 15:52:47 -07:00
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Copy constructor. Create an object containing the same value as @p other and in the same state.
|
|
|
|
* @param other Constant reference to another <tt>eina::optional</tt> object that holds the same value type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object with
|
|
|
|
* the same engagement state of @p other. If @p other is engaged then
|
|
|
|
* the contained value of the newly created object is initialized by
|
|
|
|
* copying the contained value of @p other.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
optional(optional<T> const& other)
|
|
|
|
: engaged(false)
|
|
|
|
{
|
|
|
|
if(other.engaged) _construct(*other);
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Move constructor. Create an object containing the same value as @p other and in the same state.
|
|
|
|
* @param other R-value reference to another <tt>eina::optional</tt> object that holds the same value type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object with
|
|
|
|
* the same engagement state of @p other. If @p other is engaged then
|
|
|
|
* the contained value of the newly created object is initialized by
|
|
|
|
* moving the contained value of @p other.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
optional(optional<T>&& other)
|
|
|
|
: engaged(false)
|
|
|
|
{
|
2015-02-12 17:22:50 -08:00
|
|
|
if(other.engaged) _construct(std::move(*other));
|
2014-05-02 15:52:47 -07:00
|
|
|
other._destroy();
|
|
|
|
}
|
|
|
|
|
2015-02-12 17:22:50 -08:00
|
|
|
/**
|
|
|
|
* @brief Move constructor. Create an object containing the same value as @p other and in the same state.
|
|
|
|
* @param other R-value reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object with
|
|
|
|
* the same engagement state of @p other. If @p other is engaged then
|
|
|
|
* the contained value of the newly created object is initialized by
|
|
|
|
* moving the contained value of @p other.
|
|
|
|
*/
|
|
|
|
template <typename U>
|
|
|
|
optional(optional<U>&& other, typename std::enable_if<std::is_convertible<U, T>::value>::type* = 0)
|
|
|
|
: engaged(false)
|
|
|
|
{
|
|
|
|
if (other.is_engaged()) _construct(std::move(*other));
|
|
|
|
other.disengage();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Copy constructor. Create an object containing the same value as @p other and in the same state.
|
|
|
|
* @param other Constant reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object with
|
|
|
|
* the same engagement state of @p other. If @p other is engaged then
|
|
|
|
* the contained value of the newly created object is initialized by
|
|
|
|
* converting and copying the contained value of @p other.
|
|
|
|
*/
|
|
|
|
template <typename U>
|
|
|
|
optional(optional<U> const& other, typename std::enable_if<std::is_convertible<U, T>::value>::type* = 0)
|
|
|
|
: engaged(false)
|
|
|
|
{
|
|
|
|
if (other.is_engaged()) _construct(*other);
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Assign new content to the object.
|
|
|
|
* @param other R-value reference to another <tt>eina::optional</tt> object that holds the same value type.
|
|
|
|
*
|
|
|
|
* This operator replaces the current content of the object. If
|
|
|
|
* @p other is engaged its contained value is moved to this object,
|
|
|
|
* making <tt>*this</tt> be considered engaged too. If @p other is
|
|
|
|
* disengaged <tt>*this</tt> is also made disengaged and its
|
|
|
|
* contained value, if any, is simple destroyed.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
_self_type& operator=(optional<T>&& other)
|
|
|
|
{
|
|
|
|
_destroy();
|
2015-02-12 17:22:50 -08:00
|
|
|
if (other.engaged)
|
2014-05-02 15:52:47 -07:00
|
|
|
_construct(std::move(*other));
|
|
|
|
other._destroy();
|
|
|
|
return *this;
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Assign new content to the object.
|
|
|
|
* @param other Constant reference to another <tt>eina::optional</tt> object that holds the same value type.
|
|
|
|
*
|
|
|
|
* This operator replaces the current content of the object. If
|
|
|
|
* @p other is engaged its contained value is copied to this object,
|
|
|
|
* making <tt>*this</tt> be considered engaged too. If @p other is
|
|
|
|
* disengaged <tt>*this</tt> is also made disengaged and its
|
|
|
|
* contained value, if any, is simple destroyed.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
_self_type& operator=(optional<T>const& other)
|
|
|
|
{
|
|
|
|
optional<T> tmp(other);
|
|
|
|
tmp.swap(*this);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-02-12 17:22:50 -08:00
|
|
|
/**
|
|
|
|
* @brief Assign new content to the object.
|
|
|
|
* @param other R-value reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
|
|
|
|
*
|
|
|
|
* This operator replaces the current content of the object. If
|
|
|
|
* @p other is engaged its contained value is moved to this object,
|
|
|
|
* making <tt>*this</tt> be considered engaged too. If @p other is
|
|
|
|
* disengaged <tt>*this</tt> is also made disengaged and its
|
|
|
|
* contained value, if any, is simple destroyed.
|
|
|
|
*/
|
|
|
|
template <typename U>
|
|
|
|
typename std::enable_if<std::is_convertible<U, T>::value, _self_type>::type& operator=(optional<U>&& other)
|
|
|
|
{
|
|
|
|
_destroy();
|
|
|
|
if (other.is_engaged())
|
|
|
|
_construct(std::move(*other));
|
|
|
|
other.disengage();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Assign new content to the object.
|
|
|
|
* @param other Constant reference to another <tt>eina::optional</tt> object that holds a different, but convertible, value type.
|
|
|
|
*
|
|
|
|
* This operator replaces the current content of the object. If
|
|
|
|
* @p other is engaged its contained value is converted and copied to this
|
|
|
|
* object, making <tt>*this</tt> be considered engaged too. If @p other is
|
|
|
|
* disengaged <tt>*this</tt> is also made disengaged and its
|
|
|
|
* contained value, if any, is simple destroyed.
|
|
|
|
*/
|
|
|
|
template <typename U>
|
|
|
|
typename std::enable_if<std::is_convertible<U, T>::value, _self_type>::type& operator=(optional<U>const& other)
|
|
|
|
{
|
|
|
|
_destroy();
|
|
|
|
if (other.is_engaged())
|
|
|
|
_construct(*other);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Disengage the object, destroying the current contained value, if any.
|
|
|
|
*/
|
|
|
|
void disengage()
|
|
|
|
{
|
|
|
|
_destroy();
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Releases the contained value if the object is engaged.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
~optional()
|
|
|
|
{
|
|
|
|
_destroy();
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Convert to @c bool based on whether the object is engaged or not.
|
|
|
|
* @return @c true if the object is engaged, @c false otherwise.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
explicit operator bool() const
|
|
|
|
{
|
|
|
|
return is_engaged();
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Convert to @c bool based on whether the object is engaged or not.
|
|
|
|
* @return @c true if the object is disengaged, @c false otherwise.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
bool operator!() const
|
|
|
|
{
|
|
|
|
bool b ( *this );
|
|
|
|
return !b;
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Access member of the contained value.
|
|
|
|
* @return Pointer to the contained value, whose member will be accessed.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
T* operator->()
|
|
|
|
{
|
|
|
|
assert(is_engaged());
|
|
|
|
return static_cast<T*>(static_cast<void*>(&buffer));
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Access constant member of the contained value.
|
|
|
|
* @return Constant pointer to the contained value, whose member will be accessed.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
T const* operator->() const
|
|
|
|
{
|
|
|
|
return const_cast<_self_type&>(*this).operator->();
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Reference to the contained value.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
T& operator*() { return get(); }
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Constant reference to the contained value.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
T const& operator*() const { return get(); }
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Reference to the contained value.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
T& get() { return *this->operator->(); }
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Constant reference to the contained value.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
T const& get() const { return *this->operator->(); }
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Swap content with another <tt>eina::optional</tt> object.
|
|
|
|
* @param other Another <tt>eina::optional</tt> object.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
void swap(optional<T>& other)
|
|
|
|
{
|
|
|
|
if(is_engaged() && other.is_engaged())
|
|
|
|
{
|
|
|
|
eina::adl_swap(**this, *other);
|
|
|
|
}
|
|
|
|
else if(is_engaged())
|
|
|
|
{
|
|
|
|
other._construct(std::move(**this));
|
|
|
|
_destroy();
|
|
|
|
}
|
|
|
|
else if(other.is_engaged())
|
|
|
|
{
|
|
|
|
_construct(std::move(*other));
|
|
|
|
other._destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Check if the object is engaged.
|
|
|
|
* @return @c true if the object is currently engaged, @c false otherwise.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
bool is_engaged() const
|
|
|
|
{
|
|
|
|
return engaged;
|
|
|
|
}
|
|
|
|
private:
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename U>
|
|
|
|
void _construct(U&& object)
|
|
|
|
{
|
|
|
|
assert(!is_engaged());
|
2019-07-12 06:07:27 -07:00
|
|
|
// NOTE: the buffer memory is intended to be in an
|
|
|
|
// uninitialized state here.
|
|
|
|
// So this warning can be disabled.
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#ifndef __clang__
|
|
|
|
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
|
|
|
#endif
|
2015-02-12 17:22:50 -08:00
|
|
|
new (&buffer) T(std::forward<U>(object));
|
2019-07-12 06:07:27 -07:00
|
|
|
#pragma GCC diagnostic pop
|
2014-05-02 15:52:47 -07:00
|
|
|
engaged = true;
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
void _destroy()
|
|
|
|
{
|
|
|
|
if(is_engaged())
|
|
|
|
{
|
|
|
|
static_cast<T*>(static_cast<void*>(&buffer))->~T();
|
|
|
|
engaged = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef typename std::aligned_storage
|
|
|
|
<sizeof(T),std::alignment_of<T>::value>::type buffer_type;
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Member variable for holding the contained value.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
buffer_type buffer;
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag to tell whether the object is engaged or not.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
bool engaged;
|
|
|
|
};
|
|
|
|
|
2016-06-05 22:49:00 -07:00
|
|
|
template <typename T>
|
|
|
|
struct optional<T&>
|
|
|
|
{
|
|
|
|
typedef optional<T&> _self_type; /**< Type for the optional class itself. */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create a disengaged object.
|
|
|
|
*
|
|
|
|
* This constructor creates a disengaged <tt>eina::optional</tt>
|
|
|
|
* object.
|
|
|
|
*/
|
|
|
|
constexpr optional(std::nullptr_t) : pointer(nullptr)
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Default constructor. Create a disengaged object.
|
|
|
|
*/
|
|
|
|
constexpr optional() : pointer(nullptr)
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Create an engaged object by moving @p other content.
|
|
|
|
* @param other R-value reference to the desired type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object in an
|
|
|
|
* engaged state. The contained value is initialized by moving
|
|
|
|
* @p other.
|
|
|
|
*/
|
|
|
|
optional(T& other) : pointer(&other)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Copy constructor. Create an object containing the same value as @p other and in the same state.
|
|
|
|
* @param other Constant reference to another <tt>eina::optional</tt> object that holds the same value type.
|
|
|
|
*
|
|
|
|
* This constructor creates an <tt>eina::optional</tt> object with
|
|
|
|
* the same engagement state of @p other. If @p other is engaged then
|
|
|
|
* the contained value of the newly created object is initialized by
|
|
|
|
* copying the contained value of @p other.
|
|
|
|
*/
|
|
|
|
optional(_self_type const& other) = default;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Assign new content to the object.
|
|
|
|
* @param other Constant reference to another <tt>eina::optional</tt> object that holds the same value type.
|
|
|
|
*
|
|
|
|
* This operator replaces the current content of the object. If
|
|
|
|
* @p other is engaged its contained value is copied to this object,
|
|
|
|
* making <tt>*this</tt> be considered engaged too. If @p other is
|
|
|
|
* disengaged <tt>*this</tt> is also made disengaged and its
|
|
|
|
* contained value, if any, is simple destroyed.
|
|
|
|
*/
|
|
|
|
_self_type& operator=(_self_type const& other) = default;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Disengage the object, destroying the current contained value, if any.
|
|
|
|
*/
|
|
|
|
void disengage()
|
|
|
|
{
|
|
|
|
pointer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Convert to @c bool based on whether the object is engaged or not.
|
|
|
|
* @return @c true if the object is engaged, @c false otherwise.
|
|
|
|
*/
|
|
|
|
explicit operator bool() const
|
|
|
|
{
|
|
|
|
return pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Convert to @c bool based on whether the object is engaged or not.
|
|
|
|
* @return @c true if the object is disengaged, @c false otherwise.
|
|
|
|
*/
|
|
|
|
bool operator!() const
|
|
|
|
{
|
|
|
|
bool b ( *this );
|
|
|
|
return !b;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Access member of the contained value.
|
|
|
|
* @return Pointer to the contained value, whose member will be accessed.
|
|
|
|
*/
|
|
|
|
T* operator->()
|
|
|
|
{
|
|
|
|
assert(is_engaged());
|
|
|
|
return pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Access constant member of the contained value.
|
|
|
|
* @return Constant pointer to the contained value, whose member will be accessed.
|
|
|
|
*/
|
|
|
|
T const* operator->() const
|
|
|
|
{
|
|
|
|
return pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Reference to the contained value.
|
|
|
|
*/
|
|
|
|
T& operator*() { return get(); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Constant reference to the contained value.
|
|
|
|
*/
|
|
|
|
T const& operator*() const { return get(); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Reference to the contained value.
|
|
|
|
*/
|
|
|
|
T& get() { return *this->operator->(); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the contained value.
|
|
|
|
* @return Constant reference to the contained value.
|
|
|
|
*/
|
|
|
|
T const& get() const { return *this->operator->(); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Swap content with another <tt>eina::optional</tt> object.
|
|
|
|
* @param other Another <tt>eina::optional</tt> object.
|
|
|
|
*/
|
|
|
|
void swap(optional<T>& other)
|
|
|
|
{
|
|
|
|
std::swap(pointer, other.pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Check if the object is engaged.
|
|
|
|
* @return @c true if the object is currently engaged, @c false otherwise.
|
|
|
|
*/
|
|
|
|
bool is_engaged() const
|
|
|
|
{
|
|
|
|
return pointer;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Member variable for holding the contained value.
|
|
|
|
*/
|
|
|
|
T* pointer;
|
|
|
|
};
|
|
|
|
|
2015-02-12 17:22:50 -08:00
|
|
|
template <typename T>
|
|
|
|
constexpr optional<typename std::decay<T>::type>
|
|
|
|
make_optional(T&& value)
|
|
|
|
{
|
|
|
|
return optional<typename std::decay<T>::type>(std::forward<T>(value));
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Swap content with another <tt>eina::optional</tt> object.
|
|
|
|
*
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
void swap(optional<T>& lhs, optional<T>& rhs)
|
|
|
|
{
|
|
|
|
lhs.swap(rhs);
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @brief Check if both <tt>eina::optional</tt> object are equal.
|
|
|
|
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
|
|
|
|
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
|
|
|
|
* @return @c true if both are objects are disengaged of if both objects
|
|
|
|
* are engaged and contain the same value, @c false in all
|
|
|
|
* other cases.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
bool operator==(optional<T> const& lhs, optional<T> const& rhs)
|
|
|
|
{
|
|
|
|
if(!lhs && !rhs)
|
|
|
|
return true;
|
|
|
|
else if(!lhs || !rhs)
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return *lhs == *rhs;
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Check if the <tt>eina::optional</tt> objects are different.
|
|
|
|
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
|
|
|
|
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
|
|
|
|
* @return The opposite of @ref operator==(optional<T> const& lhs, optional<T> const& rhs).
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
bool operator!=(optional<T> const& lhs, optional<T> const& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs == rhs);
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Less than comparison between <tt>eina::optional</tt> objects.
|
|
|
|
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
|
|
|
|
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
|
|
|
|
* @return @c true if both objects are engaged and the contained value
|
|
|
|
* of @p lhs is less than the contained value of @p rhs, or if
|
|
|
|
* only @p lhs is disengaged. In all other cases returns
|
|
|
|
* @c false.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
bool operator<(optional<T> const& lhs, optional<T> const& rhs)
|
|
|
|
{
|
|
|
|
if(!lhs && !rhs)
|
|
|
|
return false;
|
|
|
|
else if(!lhs)
|
|
|
|
return true;
|
|
|
|
else if(!rhs)
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return *lhs < *rhs;
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Less than or equal comparison between <tt>eina::optional</tt> objects.
|
|
|
|
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
|
|
|
|
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
|
|
|
|
* @return @c true if @p lhs is disengaged or if both objects are
|
|
|
|
* engaged and the contained value of @p lhs is less than or
|
|
|
|
* equal to the contained value of @p rhs. In all other cases
|
|
|
|
* returns @c false.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
bool operator<=(optional<T> const& lhs, optional<T> const& rhs)
|
|
|
|
{
|
|
|
|
return lhs < rhs || lhs == rhs;
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief More than comparison between <tt>eina::optional</tt> objects.
|
|
|
|
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
|
|
|
|
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
|
|
|
|
* @return @c true if both objects are engaged and the contained value
|
|
|
|
* of @p lhs is more than the contained value of @p rhs, or if
|
|
|
|
* only @p rhs is disengaged. In all other cases returns
|
|
|
|
* @c false.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
bool operator>(optional<T> const& lhs, optional<T> const& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs <= rhs);
|
|
|
|
}
|
2014-06-04 13:34:42 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief More than or equal comparison between <tt>eina::optional</tt> objects.
|
|
|
|
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
|
|
|
|
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
|
|
|
|
* @return @c true if @p rhs is disengaged or if both objects are
|
|
|
|
* engaged and the contained value of @p lhs is more than or
|
|
|
|
* equal to the contained value of @p rhs. In all other
|
|
|
|
* cases returns @c false.
|
|
|
|
*/
|
2014-05-02 15:52:47 -07:00
|
|
|
template <typename T>
|
|
|
|
bool operator>=(optional<T> const& lhs, optional<T> const& rhs)
|
|
|
|
{
|
|
|
|
return !(lhs < rhs);
|
|
|
|
}
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2014-05-02 15:52:47 -07:00
|
|
|
} } // efl::eina
|
|
|
|
|
2014-06-04 13:34:42 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2014-05-02 15:52:47 -07:00
|
|
|
#endif // EINA_OPTIONAL_HH_
|