Add all the relational operators to std::experimental::optional. Also update bad_optional_access to match the Library Fundamentals draft standard. This is not all of the upcoming changes to optional, though.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@223775 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Marshall Clow
2014-12-09 14:49:17 +00:00
parent fff544efbd
commit 4ad67e08cb
24 changed files with 1047 additions and 266 deletions

View File

@@ -16,131 +16,147 @@
// C++1y
#include <initializer_list>
namespace std { namespace experimental { inline namespace fundamentals_v1 {
namespace std { namespace experimental {
// 5.3, optional for object types
template <class T> class optional;
// optional for object types
template <class T>
class optional
{
public:
typedef T value_type;
// 5.4, In-place construction
struct in_place_t{};
constexpr in_place_t in_place{};
// constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
optional(const optional&);
optional(optional&&) noexcept(is_nothrow_move_constructible<T>::value);
constexpr optional(const T&);
constexpr optional(T&&);
template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
// 5.5, No-value state indicator
struct nullopt_t{see below};
constexpr nullopt_t nullopt(unspecified);
// destructor
~optional();
// 5.6, Class bad_optional_access
class bad_optional_access;
// assignment
optional& operator=(nullopt_t) noexcept;
optional& operator=(const optional&);
optional& operator=(optional&&)
noexcept(is_nothrow_move_assignable<T>::value &&
is_nothrow_move_constructible<T>::value);
template <class U> optional& operator=(U&&);
template <class... Args> void emplace(Args&&...);
template <class U, class... Args> void emplace(initializer_list<U>, Args&&...);
// 5.7, Relational operators
template <class T>
constexpr bool operator==(const optional<T>&, const optional<T>&);
template <class T>
constexpr bool operator!=(const optional<T>&, const optional<T>&);
template <class T>
constexpr bool operator<(const optional<T>&, const optional<T>&);
template <class T>
constexpr bool operator>(const optional<T>&, const optional<T>&);
template <class T>
constexpr bool operator<=(const optional<T>&, const optional<T>&);
template <class T>
constexpr bool operator>=(const optional<T>&, const optional<T>&);
// swap
void swap(optional&)
noexcept(is_nothrow_move_constructible<T>::value &&
noexcept(swap(declval<T&>(), declval<T&>())));
// 5.8, Comparison with nullopt
template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
// observers
constexpr T const* operator->() const;
T* operator->();
constexpr T const& operator*() const;
T& operator*();
constexpr explicit operator bool() const noexcept;
constexpr T const& value() const;
T& value();
template <class U> constexpr T value_or(U&&) const&;
template <class U> T value_or(U&&) &&;
};
// 5.9, Comparison with T
template <class T> constexpr bool operator==(const optional<T>&, const T&);
template <class T> constexpr bool operator==(const T&, const optional<T>&);
template <class T> constexpr bool operator!=(const optional<T>&, const T&);
template <class T> constexpr bool operator!=(const T&, const optional<T>&);
template <class T> constexpr bool operator<(const optional<T>&, const T&);
template <class T> constexpr bool operator<(const T&, const optional<T>&);
template <class T> constexpr bool operator<=(const optional<T>&, const T&);
template <class T> constexpr bool operator<=(const T&, const optional<T>&);
template <class T> constexpr bool operator>(const optional<T>&, const T&);
template <class T> constexpr bool operator>(const T&, const optional<T>&);
template <class T> constexpr bool operator>=(const optional<T>&, const T&);
template <class T> constexpr bool operator>=(const T&, const optional<T>&);
// In-place construction
struct in_place_t{};
constexpr in_place_t in_place{};
// 5.10, Specialized algorithms
template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
template <class T> constexpr optional<see below> make_optional(T&&);
// Disengaged state indicator
struct nullopt_t{see below};
constexpr nullopt_t nullopt(unspecified);
template <class T>
class optional
{
public:
typedef T value_type;
// class bad_optional_access
class bad_optional_access
: public logic_error
{
public:
explicit bad_optional_access(const string& what_arg);
explicit bad_optional_access(const char* what_arg);
};
// 5.3.1, Constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
optional(const optional&);
optional(optional&&) noexcept(see below);
constexpr optional(const T&);
constexpr optional(T&&);
template <class... Args> constexpr explicit optional(in_place_t, Args&&...);
template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...);
// Relational operators
template <class T> constexpr bool operator==(const optional<T>&, const optional<T>&);
template <class T> constexpr bool operator< (const optional<T>&, const optional<T>&);
// 5.3.2, Destructor
~optional();
// Comparison with nullopt
template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
// 5.3.3, Assignment
optional& operator=(nullopt_t) noexcept;
optional& operator=(const optional&);
optional& operator=(optional&&) noexcept(see below);
template <class U> optional& operator=(U&&);
template <class... Args> void emplace(Args&&...);
template <class U, class... Args>
void emplace(initializer_list<U>, Args&&...);
// Comparison with T
template <class T> constexpr bool operator==(const optional<T>&, const T&);
template <class T> constexpr bool operator==(const T&, const optional<T>&);
template <class T> constexpr bool operator<(const optional<T>&, const T&);
template <class T> constexpr bool operator<(const T&, const optional<T>&);
// 5.3.4, Swap
void swap(optional&) noexcept(see below);
// Specialized algorithms
template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below);
template <class T> constexpr optional<typename decay<T>::type> make_optional(T&&);
// 5.3.5, Observers
constexpr T const* operator ->() const;
constexpr T* operator ->();
constexpr T const& operator *() const &;
constexpr T& operator *() &;
constexpr T&& operator *() &&;
constexpr const T&& operator *() const &&;
constexpr explicit operator bool() const noexcept;
constexpr T const& value() const &;
constexpr T& value() &;
constexpr T&& value() &&;
constexpr const T&& value() const &&;
template <class U> constexpr T value_or(U&&) const &;
template <class U> constexpr T value_or(U&&) &&;
// hash support
template <class T> struct hash;
template <class T> struct hash<optional<T>>;
private:
T* val; // exposition only
};
}} // std::experimental
} // namespace fundamentals_v1
} // namespace experimental
// 5.11, Hash support
template <class T> struct hash;
template <class T> struct hash<experimental::optional<T>>;
} // namespace std
*/
#include <__config>
#include <experimental/__config>
#include <functional>
#include <stdexcept>
namespace std { namespace experimental {
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
class _LIBCPP_EXCEPTION_ABI bad_optional_access
: public logic_error
: public std::logic_error
{
public:
#if _LIBCPP_STD_VER > 11
_LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const string& __arg)
: logic_error(__arg) {}
_LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const char* __arg)
: logic_error(__arg) {}
_LIBCPP_INLINE_VISIBILITY bad_optional_access(const bad_optional_access&) noexcept = default;
_LIBCPP_INLINE_VISIBILITY bad_optional_access& operator=(const bad_optional_access&) noexcept = default;
#else
private:
bad_optional_access(const bad_optional_access&);
bad_optional_access& operator=(const bad_optional_access&);
public:
#endif // _LIBCPP_STD_VER > 11
// Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y
bad_optional_access() : std::logic_error("Bad optional Access") {}
// Get the key function ~bad_optional_access() into the dylib
virtual ~bad_optional_access() _NOEXCEPT;
};
}} // std::experimental
_LIBCPP_END_NAMESPACE_EXPERIMENTAL
#if _LIBCPP_STD_VER > 11
@@ -148,16 +164,14 @@ public:
#include <type_traits>
#include <new>
#include <__functional_base>
#include <__undef_min_max>
#include <__debug>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
namespace std { namespace experimental { inline namespace __library_fundamentals_v1 {
_LIBCPP_BEGIN_NAMESPACE_LFTS
struct in_place_t {};
constexpr in_place_t in_place{};
@@ -503,7 +517,7 @@ public:
constexpr value_type const& value() const
{
if (!this->__engaged_)
throw bad_optional_access("optional<T>::value: not engaged");
throw bad_optional_access();
return this->__val_;
}
@@ -511,7 +525,7 @@ public:
value_type& value()
{
if (!this->__engaged_)
throw bad_optional_access("optional<T>::value: not engaged");
throw bad_optional_access();
return this->__val_;
}
@@ -556,6 +570,7 @@ private:
}
};
// Comparisons between optionals
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
@@ -569,6 +584,15 @@ operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
return *__x == *__y;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
{
return !(__x == __y);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
@@ -579,9 +603,38 @@ operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
return false;
if (!static_cast<bool>(__x))
return true;
return less<_Tp>{}(*__x, *__y);
return *__x < *__y;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
{
return __y < __x;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
{
return !(__y < __x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y)
{
return !(__x < __y);
}
// Comparisons with nullopt
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
@@ -600,6 +653,24 @@ operator==(nullopt_t, const optional<_Tp>& __x) noexcept
return !static_cast<bool>(__x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
{
return static_cast<bool>(__x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
{
return static_cast<bool>(__x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
@@ -618,6 +689,61 @@ operator<(nullopt_t, const optional<_Tp>& __x) noexcept
return static_cast<bool>(__x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
{
return !static_cast<bool>(__x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator<=(nullopt_t, const optional<_Tp>& __x) noexcept
{
return true;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>(const optional<_Tp>& __x, nullopt_t) noexcept
{
return static_cast<bool>(__x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>(nullopt_t, const optional<_Tp>& __x) noexcept
{
return false;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>=(const optional<_Tp>&, nullopt_t) noexcept
{
return true;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
{
return !static_cast<bool>(__x);
}
// Comparisons with T
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
@@ -636,6 +762,24 @@ operator==(const _Tp& __v, const optional<_Tp>& __x)
return static_cast<bool>(__x) ? *__x == __v : false;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator!=(const optional<_Tp>& __x, const _Tp& __v)
{
return static_cast<bool>(__x) ? !(*__x == __v) : true;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator!=(const _Tp& __v, const optional<_Tp>& __x)
{
return static_cast<bool>(__x) ? !(*__x == __v) : true;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
@@ -654,6 +798,61 @@ operator<(const _Tp& __v, const optional<_Tp>& __x)
return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator<=(const optional<_Tp>& __x, const _Tp& __v)
{
return !(__x > __v);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator<=(const _Tp& __v, const optional<_Tp>& __x)
{
return !(__v > __x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>(const optional<_Tp>& __x, const _Tp& __v)
{
return static_cast<bool>(__x) ? __v < __x : false;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>(const _Tp& __v, const optional<_Tp>& __x)
{
return static_cast<bool>(__x) ? __x < __v : true;
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>=(const optional<_Tp>& __x, const _Tp& __v)
{
return !(__x < __v);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
constexpr
bool
operator>=(const _Tp& __v, const optional<_Tp>& __x)
{
return !(__v < __x);
}
template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
void
@@ -671,7 +870,7 @@ make_optional(_Tp&& __v)
return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v));
}
}}} // namespace std::experimental::__library_fundamentals_v1
_LIBCPP_END_NAMESPACE_LFTS
_LIBCPP_BEGIN_NAMESPACE_STD