From 82a91b3afeac9aab63e3627c0aee4c341e0dcbb2 Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 15:42:46 +0300 Subject: [PATCH 1/9] Import experimental/optional from libc++ 3.5, under MIT license --- SDL2pp/libcpp_optional.hh | 699 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 699 insertions(+) create mode 100644 SDL2pp/libcpp_optional.hh diff --git a/SDL2pp/libcpp_optional.hh b/SDL2pp/libcpp_optional.hh new file mode 100644 index 0000000..3848da8 --- /dev/null +++ b/SDL2pp/libcpp_optional.hh @@ -0,0 +1,699 @@ +// -*- C++ -*- +//===-------------------------- optional ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_OPTIONAL +#define _LIBCPP_OPTIONAL + +/* + optional synopsis + +// C++1y + +#include + +namespace std { namespace experimental { + +// optional for object types +template +class optional +{ +public: + typedef T value_type; + + // constructors + constexpr optional() noexcept; + constexpr optional(nullopt_t) noexcept; + optional(const optional&); + optional(optional&&) noexcept(is_nothrow_move_constructible::value); + constexpr optional(const T&); + constexpr optional(T&&); + template constexpr explicit optional(in_place_t, Args&&...); + template + constexpr explicit optional(in_place_t, initializer_list, Args&&...); + + // destructor + ~optional(); + + // assignment + optional& operator=(nullopt_t) noexcept; + optional& operator=(const optional&); + optional& operator=(optional&&) + noexcept(is_nothrow_move_assignable::value && + is_nothrow_move_constructible::value); + template optional& operator=(U&&); + template void emplace(Args&&...); + template void emplace(initializer_list, Args&&...); + + // swap + void swap(optional&) + noexcept(is_nothrow_move_constructible::value && + noexcept(swap(declval(), declval()))); + + // 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 constexpr T value_or(U&&) const&; + template T value_or(U&&) &&; +}; + +// In-place construction +struct in_place_t{}; +constexpr in_place_t in_place{}; + +// Disengaged state indicator +struct nullopt_t{see below}; +constexpr nullopt_t nullopt(unspecified); + +// 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); +}; + +// Relational operators +template constexpr bool operator==(const optional&, const optional&); +template constexpr bool operator< (const optional&, const optional&); + +// Comparison with nullopt +template constexpr bool operator==(const optional&, nullopt_t) noexcept; +template constexpr bool operator==(nullopt_t, const optional&) noexcept; +template constexpr bool operator<(const optional&, nullopt_t) noexcept; +template constexpr bool operator<(nullopt_t, const optional&) noexcept; + +// Comparison with T +template constexpr bool operator==(const optional&, const T&); +template constexpr bool operator==(const T&, const optional&); +template constexpr bool operator<(const optional&, const T&); +template constexpr bool operator<(const T&, const optional&); + +// Specialized algorithms +template void swap(optional&, optional&) noexcept(see below); +template constexpr optional::type> make_optional(T&&); + +// hash support +template struct hash; +template struct hash>; + +}} // std::experimental + +*/ + +#include <__config> +#include +#include + +namespace std { namespace experimental { + +class _LIBCPP_EXCEPTION_ABI bad_optional_access + : public 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 + virtual ~bad_optional_access() _NOEXCEPT; +}; + +}} // std::experimental + +#if _LIBCPP_STD_VER > 11 + +#include +#include +#include +#include <__functional_base> + +#include <__undef_min_max> + +#ifdef _LIBCPP_DEBUG +# include <__debug> +#else +# define _LIBCPP_ASSERT(x, m) ((void)0) +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +namespace std { namespace experimental { inline namespace __library_fundamentals_v1 { + +struct in_place_t {}; +constexpr in_place_t in_place{}; + +struct nullopt_t +{ + explicit constexpr nullopt_t(int) noexcept {} +}; + +constexpr nullopt_t nullopt{0}; + +template ::value> +class __optional_storage +{ +protected: + typedef _Tp value_type; + union + { + char __null_state_; + value_type __val_; + }; + bool __engaged_ = false; + + _LIBCPP_INLINE_VISIBILITY + ~__optional_storage() + { + if (__engaged_) + __val_.~value_type(); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_storage() noexcept + : __null_state_('\0') {} + + _LIBCPP_INLINE_VISIBILITY + __optional_storage(const __optional_storage& __x) + : __engaged_(__x.__engaged_) + { + if (__engaged_) + ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); + } + + _LIBCPP_INLINE_VISIBILITY + __optional_storage(__optional_storage&& __x) + noexcept(is_nothrow_move_constructible::value) + : __engaged_(__x.__engaged_) + { + if (__engaged_) + ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_storage(const value_type& __v) + : __val_(__v), + __engaged_(true) {} + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_storage(value_type&& __v) + : __val_(_VSTD::move(__v)), + __engaged_(true) {} + + template + _LIBCPP_INLINE_VISIBILITY + constexpr + explicit __optional_storage(in_place_t, _Args&&... __args) + : __val_(_VSTD::forward<_Args>(__args)...), + __engaged_(true) {} +}; + +template +class __optional_storage<_Tp, true> +{ +protected: + typedef _Tp value_type; + union + { + char __null_state_; + value_type __val_; + }; + bool __engaged_ = false; + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_storage() noexcept + : __null_state_('\0') {} + + _LIBCPP_INLINE_VISIBILITY + __optional_storage(const __optional_storage& __x) + : __engaged_(__x.__engaged_) + { + if (__engaged_) + ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); + } + + _LIBCPP_INLINE_VISIBILITY + __optional_storage(__optional_storage&& __x) + noexcept(is_nothrow_move_constructible::value) + : __engaged_(__x.__engaged_) + { + if (__engaged_) + ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_storage(const value_type& __v) + : __val_(__v), + __engaged_(true) {} + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_storage(value_type&& __v) + : __val_(_VSTD::move(__v)), + __engaged_(true) {} + + template + _LIBCPP_INLINE_VISIBILITY + constexpr + explicit __optional_storage(in_place_t, _Args&&... __args) + : __val_(_VSTD::forward<_Args>(__args)...), + __engaged_(true) {} +}; + +template +class optional + : private __optional_storage<_Tp> +{ + typedef __optional_storage<_Tp> __base; +public: + typedef _Tp value_type; + + static_assert(!is_reference::value, + "Instantiation of optional with a reference type is ill-formed."); + static_assert(!is_same::type, in_place_t>::value, + "Instantiation of optional with a in_place_t type is ill-formed."); + static_assert(!is_same::type, nullopt_t>::value, + "Instantiation of optional with a nullopt_t type is ill-formed."); + static_assert(is_object::value, + "Instantiation of optional with a non-object type is undefined behavior."); + static_assert(is_nothrow_destructible::value, + "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior."); + + _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} + _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default; + _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default; + _LIBCPP_INLINE_VISIBILITY ~optional() = default; + _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} + _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v) + : __base(__v) {} + _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v) + : __base(_VSTD::move(__v)) {} + + template ::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + constexpr + explicit optional(in_place_t, _Args&&... __args) + : __base(in_place, _VSTD::forward<_Args>(__args)...) {} + + template &, _Args...>::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + constexpr + explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} + + _LIBCPP_INLINE_VISIBILITY + optional& operator=(nullopt_t) noexcept + { + if (this->__engaged_) + { + this->__val_.~value_type(); + this->__engaged_ = false; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + optional& + operator=(const optional& __opt) + { + if (this->__engaged_ == __opt.__engaged_) + { + if (this->__engaged_) + this->__val_ = __opt.__val_; + } + else + { + if (this->__engaged_) + this->__val_.~value_type(); + else + ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_); + this->__engaged_ = __opt.__engaged_; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + optional& + operator=(optional&& __opt) + noexcept(is_nothrow_move_assignable::value && + is_nothrow_move_constructible::value) + { + if (this->__engaged_ == __opt.__engaged_) + { + if (this->__engaged_) + this->__val_ = _VSTD::move(__opt.__val_); + } + else + { + if (this->__engaged_) + this->__val_.~value_type(); + else + ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); + this->__engaged_ = __opt.__engaged_; + } + return *this; + } + + template ::type, value_type>::value && + is_constructible::value && + is_assignable::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + optional& + operator=(_Up&& __v) + { + if (this->__engaged_) + this->__val_ = _VSTD::forward<_Up>(__v); + else + { + ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v)); + this->__engaged_ = true; + } + return *this; + } + + template ::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + void + emplace(_Args&&... __args) + { + *this = nullopt; + ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); + this->__engaged_ = true; + } + + template &, _Args...>::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + void + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + *this = nullopt; + ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...); + this->__engaged_ = true; + } + + _LIBCPP_INLINE_VISIBILITY + void + swap(optional& __opt) + noexcept(is_nothrow_move_constructible::value && + __is_nothrow_swappable::value) + { + using _VSTD::swap; + if (this->__engaged_ == __opt.__engaged_) + { + if (this->__engaged_) + swap(this->__val_, __opt.__val_); + } + else + { + if (this->__engaged_) + { + ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_)); + this->__val_.~value_type(); + } + else + { + ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); + __opt.__val_.~value_type(); + } + swap(this->__engaged_, __opt.__engaged_); + } + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + value_type const* + operator->() const + { + _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); + return __operator_arrow(__has_operator_addressof{}); + } + + _LIBCPP_INLINE_VISIBILITY + value_type* + operator->() + { + _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); + return _VSTD::addressof(this->__val_); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + const value_type& + operator*() const + { + _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); + return this->__val_; + } + + _LIBCPP_INLINE_VISIBILITY + value_type& + operator*() + { + _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); + return this->__val_; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr explicit operator bool() const noexcept {return this->__engaged_;} + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type const& value() const + { + if (!this->__engaged_) + throw bad_optional_access("optional::value: not engaged"); + return this->__val_; + } + + _LIBCPP_INLINE_VISIBILITY + value_type& value() + { + if (!this->__engaged_) + throw bad_optional_access("optional::value: not engaged"); + return this->__val_; + } + + template + _LIBCPP_INLINE_VISIBILITY + constexpr value_type value_or(_Up&& __v) const& + { + static_assert(is_copy_constructible::value, + "optional::value_or: T must be copy constructible"); + static_assert(is_convertible<_Up, value_type>::value, + "optional::value_or: U must be convertible to T"); + return this->__engaged_ ? this->__val_ : + static_cast(_VSTD::forward<_Up>(__v)); + } + + template + _LIBCPP_INLINE_VISIBILITY + value_type value_or(_Up&& __v) && + { + static_assert(is_move_constructible::value, + "optional::value_or: T must be move constructible"); + static_assert(is_convertible<_Up, value_type>::value, + "optional::value_or: U must be convertible to T"); + return this->__engaged_ ? _VSTD::move(this->__val_) : + static_cast(_VSTD::forward<_Up>(__v)); + } + +private: + _LIBCPP_INLINE_VISIBILITY + value_type const* + __operator_arrow(true_type) const + { + return _VSTD::addressof(this->__val_); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + value_type const* + __operator_arrow(false_type) const + { + return &this->__val_; + } +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator==(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (static_cast(__x) != static_cast(__y)) + return false; + if (!static_cast(__x)) + return true; + return *__x == *__y; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator<(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (!static_cast(__y)) + return false; + if (!static_cast(__x)) + return true; + return less<_Tp>{}(*__x, *__y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator==(const optional<_Tp>& __x, nullopt_t) noexcept +{ + return !static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator==(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return !static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator<(const optional<_Tp>&, nullopt_t) noexcept +{ + return false; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator<(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return static_cast(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator==(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast(__x) ? *__x == __v : false; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator==(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast(__x) ? *__x == __v : false; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator<(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast(__x) ? less<_Tp>{}(*__x, __v) : true; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +bool +operator<(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast(__x) ? less<_Tp>{}(__v, *__x) : false; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) +{ + __x.swap(__y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +constexpr +optional::type> +make_optional(_Tp&& __v) +{ + return optional::type>(_VSTD::forward<_Tp>(__v)); +} + +}}} // namespace std::experimental::__library_fundamentals_v1 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TYPE_VIS_ONLY hash > +{ + typedef std::experimental::optional<_Tp> argument_type; + typedef size_t result_type; + + _LIBCPP_INLINE_VISIBILITY + result_type operator()(const argument_type& __opt) const _NOEXCEPT + { + return static_cast(__opt) ? hash<_Tp>()(*__opt) : 0; + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 11 + +#endif // _LIBCPP_ARRAY From 2dca69320eb29ce3d29563cc44d81dba26ffdd8a Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 15:44:46 +0300 Subject: [PATCH 2/9] Fix include guards --- SDL2pp/libcpp_optional.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SDL2pp/libcpp_optional.hh b/SDL2pp/libcpp_optional.hh index 3848da8..7c91512 100644 --- a/SDL2pp/libcpp_optional.hh +++ b/SDL2pp/libcpp_optional.hh @@ -8,8 +8,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP_OPTIONAL -#define _LIBCPP_OPTIONAL +#ifndef SDL2PP_LIBCPP_OPTIONAL +#define SDL2PP_LIBCPP_OPTIONAL /* optional synopsis @@ -696,4 +696,4 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_STD_VER > 11 -#endif // _LIBCPP_ARRAY +#endif // SDL2PP_LIBCPP_OPTIONAL From f35c7c9cbace09c0c54e92e87ba739eaceb4c75b Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 15:48:34 +0300 Subject: [PATCH 3/9] Remove limit in c++ standard version --- SDL2pp/libcpp_optional.hh | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/SDL2pp/libcpp_optional.hh b/SDL2pp/libcpp_optional.hh index 7c91512..b212179 100644 --- a/SDL2pp/libcpp_optional.hh +++ b/SDL2pp/libcpp_optional.hh @@ -123,27 +123,18 @@ class _LIBCPP_EXCEPTION_ABI bad_optional_access : public 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 virtual ~bad_optional_access() _NOEXCEPT; }; }} // std::experimental -#if _LIBCPP_STD_VER > 11 - #include #include #include @@ -694,6 +685,4 @@ struct _LIBCPP_TYPE_VIS_ONLY hash > _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 11 - #endif // SDL2PP_LIBCPP_OPTIONAL From bd81462de1edcf6e7c259c26ebe16b703d1bac2c Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 16:10:48 +0300 Subject: [PATCH 4/9] Untie optional from libc++ Style changes: * Change namespace: std::experimental -> SDL2pp::cpp_optional * Change _LIBCPP_BEGIN_NAMESPACE_STD to plain "namespace std {" * Remove _LIBCPP_INLINE_VISIBILITY, _LIBCPP_EXCEPTION_ABI * Change _NOEXEPT to noexcept * Address all c++ standard library primitives via std:: Functional changes: * Change _LIBCPP_ASSERT() to plain assert() * Remove constexpr from functions which require c++1y relaxed constexpr requirements * Change __is_nothrow_swappable condition for noexcept of swap(), to noexcept(std::swap) (idea taken from libstdc++) * Remove constexpr from operator-> const to not require internal __has_operator_addressof --- SDL2pp/libcpp_optional.hh | 384 +++++++++++--------------------------- 1 file changed, 106 insertions(+), 278 deletions(-) diff --git a/SDL2pp/libcpp_optional.hh b/SDL2pp/libcpp_optional.hh index b212179..7a059d8 100644 --- a/SDL2pp/libcpp_optional.hh +++ b/SDL2pp/libcpp_optional.hh @@ -11,149 +11,29 @@ #ifndef SDL2PP_LIBCPP_OPTIONAL #define SDL2PP_LIBCPP_OPTIONAL -/* - optional synopsis - -// C++1y - -#include - -namespace std { namespace experimental { - -// optional for object types -template -class optional -{ -public: - typedef T value_type; - - // constructors - constexpr optional() noexcept; - constexpr optional(nullopt_t) noexcept; - optional(const optional&); - optional(optional&&) noexcept(is_nothrow_move_constructible::value); - constexpr optional(const T&); - constexpr optional(T&&); - template constexpr explicit optional(in_place_t, Args&&...); - template - constexpr explicit optional(in_place_t, initializer_list, Args&&...); - - // destructor - ~optional(); - - // assignment - optional& operator=(nullopt_t) noexcept; - optional& operator=(const optional&); - optional& operator=(optional&&) - noexcept(is_nothrow_move_assignable::value && - is_nothrow_move_constructible::value); - template optional& operator=(U&&); - template void emplace(Args&&...); - template void emplace(initializer_list, Args&&...); - - // swap - void swap(optional&) - noexcept(is_nothrow_move_constructible::value && - noexcept(swap(declval(), declval()))); - - // 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 constexpr T value_or(U&&) const&; - template T value_or(U&&) &&; -}; - -// In-place construction -struct in_place_t{}; -constexpr in_place_t in_place{}; - -// Disengaged state indicator -struct nullopt_t{see below}; -constexpr nullopt_t nullopt(unspecified); - -// 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); -}; - -// Relational operators -template constexpr bool operator==(const optional&, const optional&); -template constexpr bool operator< (const optional&, const optional&); - -// Comparison with nullopt -template constexpr bool operator==(const optional&, nullopt_t) noexcept; -template constexpr bool operator==(nullopt_t, const optional&) noexcept; -template constexpr bool operator<(const optional&, nullopt_t) noexcept; -template constexpr bool operator<(nullopt_t, const optional&) noexcept; - -// Comparison with T -template constexpr bool operator==(const optional&, const T&); -template constexpr bool operator==(const T&, const optional&); -template constexpr bool operator<(const optional&, const T&); -template constexpr bool operator<(const T&, const optional&); - -// Specialized algorithms -template void swap(optional&, optional&) noexcept(see below); -template constexpr optional::type> make_optional(T&&); - -// hash support -template struct hash; -template struct hash>; - -}} // std::experimental - -*/ - -#include <__config> +#include #include +#include +#include #include +#include -namespace std { namespace experimental { +namespace sdl2pp_libcpp_optional { -class _LIBCPP_EXCEPTION_ABI bad_optional_access - : public logic_error +class bad_optional_access + : public std::logic_error { public: - _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; + explicit bad_optional_access(const std::string& __arg) + : std::logic_error(__arg) {} + explicit bad_optional_access(const char* __arg) + : std::logic_error(__arg) {} + bad_optional_access(const bad_optional_access&) noexcept = default; + bad_optional_access& operator=(const bad_optional_access&) noexcept = default; // Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y - virtual ~bad_optional_access() _NOEXCEPT; + virtual ~bad_optional_access() noexcept {} }; -}} // std::experimental - -#include -#include -#include -#include <__functional_base> - -#include <__undef_min_max> - -#ifdef _LIBCPP_DEBUG -# include <__debug> -#else -# define _LIBCPP_ASSERT(x, m) ((void)0) -#endif - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -#pragma GCC system_header -#endif - -namespace std { namespace experimental { inline namespace __library_fundamentals_v1 { - struct in_place_t {}; constexpr in_place_t in_place{}; @@ -164,7 +44,7 @@ struct nullopt_t constexpr nullopt_t nullopt{0}; -template ::value> +template ::value> class __optional_storage { protected: @@ -176,49 +56,42 @@ protected: }; bool __engaged_ = false; - _LIBCPP_INLINE_VISIBILITY ~__optional_storage() { if (__engaged_) __val_.~value_type(); } - _LIBCPP_INLINE_VISIBILITY constexpr __optional_storage() noexcept : __null_state_('\0') {} - _LIBCPP_INLINE_VISIBILITY __optional_storage(const __optional_storage& __x) : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); + ::new(std::addressof(__val_)) value_type(__x.__val_); } - _LIBCPP_INLINE_VISIBILITY __optional_storage(__optional_storage&& __x) - noexcept(is_nothrow_move_constructible::value) + noexcept(std::is_nothrow_move_constructible::value) : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); + ::new(std::addressof(__val_)) value_type(std::move(__x.__val_)); } - _LIBCPP_INLINE_VISIBILITY constexpr __optional_storage(const value_type& __v) : __val_(__v), __engaged_(true) {} - _LIBCPP_INLINE_VISIBILITY constexpr __optional_storage(value_type&& __v) - : __val_(_VSTD::move(__v)), + : __val_(std::move(__v)), __engaged_(true) {} template - _LIBCPP_INLINE_VISIBILITY constexpr explicit __optional_storage(in_place_t, _Args&&... __args) - : __val_(_VSTD::forward<_Args>(__args)...), + : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} }; @@ -234,42 +107,36 @@ protected: }; bool __engaged_ = false; - _LIBCPP_INLINE_VISIBILITY constexpr __optional_storage() noexcept : __null_state_('\0') {} - _LIBCPP_INLINE_VISIBILITY __optional_storage(const __optional_storage& __x) : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); + ::new(std::addressof(__val_)) value_type(__x.__val_); } - _LIBCPP_INLINE_VISIBILITY __optional_storage(__optional_storage&& __x) - noexcept(is_nothrow_move_constructible::value) + noexcept(std::is_nothrow_move_constructible::value) : __engaged_(__x.__engaged_) { if (__engaged_) - ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); + ::new(std::addressof(__val_)) value_type(std::move(__x.__val_)); } - _LIBCPP_INLINE_VISIBILITY constexpr __optional_storage(const value_type& __v) : __val_(__v), __engaged_(true) {} - _LIBCPP_INLINE_VISIBILITY constexpr __optional_storage(value_type&& __v) - : __val_(_VSTD::move(__v)), + : __val_(std::move(__v)), __engaged_(true) {} template - _LIBCPP_INLINE_VISIBILITY constexpr explicit __optional_storage(in_place_t, _Args&&... __args) - : __val_(_VSTD::forward<_Args>(__args)...), + : __val_(std::forward<_Args>(__args)...), __engaged_(true) {} }; @@ -281,50 +148,47 @@ class optional public: typedef _Tp value_type; - static_assert(!is_reference::value, + static_assert(!std::is_reference::value, "Instantiation of optional with a reference type is ill-formed."); - static_assert(!is_same::type, in_place_t>::value, + static_assert(!std::is_same::type, in_place_t>::value, "Instantiation of optional with a in_place_t type is ill-formed."); - static_assert(!is_same::type, nullopt_t>::value, + static_assert(!std::is_same::type, nullopt_t>::value, "Instantiation of optional with a nullopt_t type is ill-formed."); - static_assert(is_object::value, + static_assert(std::is_object::value, "Instantiation of optional with a non-object type is undefined behavior."); - static_assert(is_nothrow_destructible::value, + static_assert(std::is_nothrow_destructible::value, "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior."); - _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} - _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default; - _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default; - _LIBCPP_INLINE_VISIBILITY ~optional() = default; - _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} - _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v) + constexpr optional() noexcept {} + optional(const optional&) = default; + optional(optional&&) = default; + ~optional() = default; + constexpr optional(nullopt_t) noexcept {} + constexpr optional(const value_type& __v) : __base(__v) {} - _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v) - : __base(_VSTD::move(__v)) {} + constexpr optional(value_type&& __v) + : __base(std::move(__v)) {} template ::value + std::is_constructible::value >::type > - _LIBCPP_INLINE_VISIBILITY constexpr explicit optional(in_place_t, _Args&&... __args) - : __base(in_place, _VSTD::forward<_Args>(__args)...) {} + : __base(in_place, std::forward<_Args>(__args)...) {} template &, _Args...>::value + std::is_constructible&, _Args...>::value >::type > - _LIBCPP_INLINE_VISIBILITY constexpr - explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) - : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} + explicit optional(in_place_t, std::initializer_list<_Up> __il, _Args&&... __args) + : __base(in_place, __il, std::forward<_Args>(__args)...) {} - _LIBCPP_INLINE_VISIBILITY optional& operator=(nullopt_t) noexcept { if (this->__engaged_) @@ -335,7 +199,6 @@ public: return *this; } - _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional& __opt) { @@ -349,93 +212,88 @@ public: if (this->__engaged_) this->__val_.~value_type(); else - ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_); + ::new(std::addressof(this->__val_)) value_type(__opt.__val_); this->__engaged_ = __opt.__engaged_; } return *this; } - _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&& __opt) - noexcept(is_nothrow_move_assignable::value && - is_nothrow_move_constructible::value) + noexcept(std::is_nothrow_move_assignable::value && + std::is_nothrow_move_constructible::value) { if (this->__engaged_ == __opt.__engaged_) { if (this->__engaged_) - this->__val_ = _VSTD::move(__opt.__val_); + this->__val_ = std::move(__opt.__val_); } else { if (this->__engaged_) this->__val_.~value_type(); else - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); + ::new(std::addressof(this->__val_)) value_type(std::move(__opt.__val_)); this->__engaged_ = __opt.__engaged_; } return *this; } template ::type, value_type>::value && - is_constructible::value && - is_assignable::value + std::is_same::type, value_type>::value && + std::is_constructible::value && + std::is_assignable::value >::type > - _LIBCPP_INLINE_VISIBILITY optional& operator=(_Up&& __v) { if (this->__engaged_) - this->__val_ = _VSTD::forward<_Up>(__v); + this->__val_ = std::forward<_Up>(__v); else { - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v)); + ::new(std::addressof(this->__val_)) value_type(std::forward<_Up>(__v)); this->__engaged_ = true; } return *this; } template ::value + std::is_constructible::value >::type > - _LIBCPP_INLINE_VISIBILITY void emplace(_Args&&... __args) { *this = nullopt; - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); + ::new(std::addressof(this->__val_)) value_type(std::forward<_Args>(__args)...); this->__engaged_ = true; } template &, _Args...>::value + std::is_constructible&, _Args...>::value >::type > - _LIBCPP_INLINE_VISIBILITY void - emplace(initializer_list<_Up> __il, _Args&&... __args) + emplace(std::initializer_list<_Up> __il, _Args&&... __args) { *this = nullopt; - ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...); + ::new(std::addressof(this->__val_)) value_type(__il, std::forward<_Args>(__args)...); this->__engaged_ = true; } - _LIBCPP_INLINE_VISIBILITY void swap(optional& __opt) - noexcept(is_nothrow_move_constructible::value && - __is_nothrow_swappable::value) + noexcept(std::is_nothrow_move_constructible::value && + noexcept(std::swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) { - using _VSTD::swap; + using std::swap; if (this->__engaged_ == __opt.__engaged_) { if (this->__engaged_) @@ -445,64 +303,55 @@ public: { if (this->__engaged_) { - ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_)); + ::new(std::addressof(__opt.__val_)) value_type(std::move(this->__val_)); this->__val_.~value_type(); } else { - ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); + ::new(std::addressof(this->__val_)) value_type(std::move(__opt.__val_)); __opt.__val_.~value_type(); } swap(this->__engaged_, __opt.__engaged_); } } - _LIBCPP_INLINE_VISIBILITY - constexpr value_type const* operator->() const { - _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); - return __operator_arrow(__has_operator_addressof{}); + assert(this->__engaged_); // "optional operator-> called for disengaged value"); + return std::addressof(this->__val_); } - _LIBCPP_INLINE_VISIBILITY value_type* operator->() { - _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); - return _VSTD::addressof(this->__val_); + assert(this->__engaged_); // "optional operator-> called for disengaged value"); + return std::addressof(this->__val_); } - _LIBCPP_INLINE_VISIBILITY - constexpr const value_type& operator*() const { - _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); + assert(this->__engaged_); // "optional operator* called for disengaged value"); return this->__val_; } - _LIBCPP_INLINE_VISIBILITY value_type& operator*() { - _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); + assert(this->__engaged_); // "optional operator* called for disengaged value"); return this->__val_; } - _LIBCPP_INLINE_VISIBILITY constexpr explicit operator bool() const noexcept {return this->__engaged_;} - _LIBCPP_INLINE_VISIBILITY - constexpr value_type const& value() const + value_type const& value() const { if (!this->__engaged_) throw bad_optional_access("optional::value: not engaged"); return this->__val_; } - _LIBCPP_INLINE_VISIBILITY value_type& value() { if (!this->__engaged_) @@ -511,49 +360,30 @@ public: } template - _LIBCPP_INLINE_VISIBILITY constexpr value_type value_or(_Up&& __v) const& { - static_assert(is_copy_constructible::value, + static_assert(std::is_copy_constructible::value, "optional::value_or: T must be copy constructible"); - static_assert(is_convertible<_Up, value_type>::value, + static_assert(std::is_convertible<_Up, value_type>::value, "optional::value_or: U must be convertible to T"); return this->__engaged_ ? this->__val_ : - static_cast(_VSTD::forward<_Up>(__v)); + static_cast(std::forward<_Up>(__v)); } template - _LIBCPP_INLINE_VISIBILITY value_type value_or(_Up&& __v) && { - static_assert(is_move_constructible::value, + static_assert(std::is_move_constructible::value, "optional::value_or: T must be move constructible"); - static_assert(is_convertible<_Up, value_type>::value, + static_assert(std::is_convertible<_Up, value_type>::value, "optional::value_or: U must be convertible to T"); - return this->__engaged_ ? _VSTD::move(this->__val_) : - static_cast(_VSTD::forward<_Up>(__v)); - } - -private: - _LIBCPP_INLINE_VISIBILITY - value_type const* - __operator_arrow(true_type) const - { - return _VSTD::addressof(this->__val_); - } - - _LIBCPP_INLINE_VISIBILITY - constexpr - value_type const* - __operator_arrow(false_type) const - { - return &this->__val_; + return this->__engaged_ ? std::move(this->__val_) : + static_cast(std::forward<_Up>(__v)); } }; template -inline _LIBCPP_INLINE_VISIBILITY -constexpr +inline bool operator==(const optional<_Tp>& __x, const optional<_Tp>& __y) { @@ -565,8 +395,7 @@ operator==(const optional<_Tp>& __x, const optional<_Tp>& __y) } template -inline _LIBCPP_INLINE_VISIBILITY -constexpr +inline bool operator<(const optional<_Tp>& __x, const optional<_Tp>& __y) { @@ -574,11 +403,11 @@ operator<(const optional<_Tp>& __x, const optional<_Tp>& __y) return false; if (!static_cast(__x)) return true; - return less<_Tp>{}(*__x, *__y); + return std::less<_Tp>{}(*__x, *__y); } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator==(const optional<_Tp>& __x, nullopt_t) noexcept @@ -587,7 +416,7 @@ operator==(const optional<_Tp>& __x, nullopt_t) noexcept } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator==(nullopt_t, const optional<_Tp>& __x) noexcept @@ -596,7 +425,7 @@ operator==(nullopt_t, const optional<_Tp>& __x) noexcept } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator<(const optional<_Tp>&, nullopt_t) noexcept @@ -605,7 +434,7 @@ operator<(const optional<_Tp>&, nullopt_t) noexcept } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator<(nullopt_t, const optional<_Tp>& __x) noexcept @@ -614,7 +443,7 @@ operator<(nullopt_t, const optional<_Tp>& __x) noexcept } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator==(const optional<_Tp>& __x, const _Tp& __v) @@ -623,7 +452,7 @@ operator==(const optional<_Tp>& __x, const _Tp& __v) } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator==(const _Tp& __v, const optional<_Tp>& __x) @@ -632,25 +461,25 @@ operator==(const _Tp& __v, const optional<_Tp>& __x) } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator<(const optional<_Tp>& __x, const _Tp& __v) { - return static_cast(__x) ? less<_Tp>{}(*__x, __v) : true; + return static_cast(__x) ? std::less<_Tp>{}(*__x, __v) : true; } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr bool operator<(const _Tp& __v, const optional<_Tp>& __x) { - return static_cast(__x) ? less<_Tp>{}(__v, *__x) : false; + return static_cast(__x) ? std::less<_Tp>{}(__v, *__x) : false; } template -inline _LIBCPP_INLINE_VISIBILITY +inline void swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) { @@ -658,31 +487,30 @@ swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) } template -inline _LIBCPP_INLINE_VISIBILITY +inline constexpr -optional::type> +optional::type> make_optional(_Tp&& __v) { - return optional::type>(_VSTD::forward<_Tp>(__v)); + return optional::type>(std::forward<_Tp>(__v)); } -}}} // namespace std::experimental::__library_fundamentals_v1 +} // namespace sdl2pp_libcpp_optional -_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { template -struct _LIBCPP_TYPE_VIS_ONLY hash > +struct hash > { - typedef std::experimental::optional<_Tp> argument_type; + typedef sdl2pp_libcpp_optional::optional<_Tp> argument_type; typedef size_t result_type; - _LIBCPP_INLINE_VISIBILITY - result_type operator()(const argument_type& __opt) const _NOEXCEPT + result_type operator()(const argument_type& __opt) const noexcept { - return static_cast(__opt) ? hash<_Tp>()(*__opt) : 0; + return static_cast(__opt) ? std::hash<_Tp>()(*__opt) : 0; } }; -_LIBCPP_END_NAMESPACE_STD +} #endif // SDL2PP_LIBCPP_OPTIONAL From d4736c2a0dcd52787bf18970b53b952fce2d3ce0 Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 17:28:23 +0300 Subject: [PATCH 5/9] Add SDL2pp wrapper for optional With future C++ standards, library will switch to std::optional, however for now we need a wrapper to choose between our bundled implementation, std::experimental::optional (if that's available) and std::optional (when that's available) --- SDL2pp/Optional.hh | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 SDL2pp/Optional.hh diff --git a/SDL2pp/Optional.hh b/SDL2pp/Optional.hh new file mode 100644 index 0000000..8641d1b --- /dev/null +++ b/SDL2pp/Optional.hh @@ -0,0 +1,38 @@ +/* + libSDL2pp - C++11 bindings/wrapper for SDL2 + Copyright (C) 2014 Dmitry Marakasov + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL2PP_OPTIONAL_HH +#define SDL2PP_OPTIONAL_HH + +#include + +namespace SDL2pp { + +template +using Optional = sdl2pp_libcpp_optional::optional; + +using BadOptionalAccess = sdl2pp_libcpp_optional::bad_optional_access; + +constexpr sdl2pp_libcpp_optional::nullopt_t NullOpt = sdl2pp_libcpp_optional::nullopt; + +} + +#endif From e6b31930b6e7674bc1d60f1469011a07f1a5a7f7 Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 17:31:14 +0300 Subject: [PATCH 6/9] Add test for optional --- tests/CMakeLists.txt | 1 + tests/test_optional.cc | 83 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tests/test_optional.cc diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index aeb6025..d76df00 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,7 @@ SET(CLI_TESTS test_pointrect test_rwops + test_optional ) # tests which test graphics functionality and thus requre working diff --git a/tests/test_optional.cc b/tests/test_optional.cc new file mode 100644 index 0000000..4b405ea --- /dev/null +++ b/tests/test_optional.cc @@ -0,0 +1,83 @@ +#include + +#include + +#include "testing.h" + +using namespace SDL2pp; + +BEGIN_TEST() + // Engage/disengage + { + Optional o; + int i; + + // disengaged + EXPECT_TRUE((bool)!o); + + // accessing disengaged fails + EXPECT_EXCEPTION(i = o.value(), BadOptionalAccess); + EXPECT_EXCEPTION(i = o.value(), std::logic_error); + + // value_or test + EXPECT_EQUAL(i = o.value_or(234), 234); + + // engage + o = 123; + + // engaged + EXPECT_TRUE((bool)o); + + // accessing value + EXPECT_EQUAL(o.value(), 123); + + // disengage + o = NullOpt; + + EXPECT_TRUE((bool)!o); + } + + // Equality + { + Optional o1, o2; + + EXPECT_TRUE(o1 == o2); + EXPECT_TRUE(o1 == NullOpt); + EXPECT_TRUE(NullOpt == o1); + + o1 = 123; + + EXPECT_TRUE(!(o1 == o2)); + + o2 = 124; + + EXPECT_TRUE(!(o1 == o2)); + + o2 = 123; + + EXPECT_TRUE(o1 == o2); + } + + // Swap + { + Optional o1, o2; + + o1 = 123; + + EXPECT_TRUE(!o2); + EXPECT_TRUE((bool)o1); + EXPECT_TRUE(o1 == 123); + + std::swap(o1, o2); + + EXPECT_TRUE(!o1); + EXPECT_TRUE((bool)o2); + EXPECT_TRUE(o2 == 123); + + o1.swap(o2); + + EXPECT_TRUE(!o2); + EXPECT_TRUE((bool)o1); + EXPECT_TRUE(o1 == 123); + } +END_TEST() From c576b6bc67cbac60a7d9dec546ed28f749700d1c Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 17:39:43 +0300 Subject: [PATCH 7/9] Fix build with broken libstdc++ --- SDL2pp/libcpp_optional.hh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SDL2pp/libcpp_optional.hh b/SDL2pp/libcpp_optional.hh index 7a059d8..6a21c19 100644 --- a/SDL2pp/libcpp_optional.hh +++ b/SDL2pp/libcpp_optional.hh @@ -28,8 +28,10 @@ public: : std::logic_error(__arg) {} explicit bad_optional_access(const char* __arg) : std::logic_error(__arg) {} - bad_optional_access(const bad_optional_access&) noexcept = default; - bad_optional_access& operator=(const bad_optional_access&) noexcept = default; + // Remove explicitly defaulted copy constructor and assignment operator: + // noexcept specification doesn't work well with libstdc++ + //bad_optional_access(const bad_optional_access&) noexcept = default; + //bad_optional_access& operator=(const bad_optional_access&) noexcept = default; // Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y virtual ~bad_optional_access() noexcept {} }; From 17053c2babe56896fd62b9aac059852675e1a119 Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 19:40:50 +0300 Subject: [PATCH 8/9] Move cpp_optional into separate directory --- SDL2pp/Optional.hh | 2 +- SDL2pp/{ => external}/libcpp_optional.hh | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename SDL2pp/{ => external}/libcpp_optional.hh (100%) diff --git a/SDL2pp/Optional.hh b/SDL2pp/Optional.hh index 8641d1b..3c647c8 100644 --- a/SDL2pp/Optional.hh +++ b/SDL2pp/Optional.hh @@ -22,7 +22,7 @@ #ifndef SDL2PP_OPTIONAL_HH #define SDL2PP_OPTIONAL_HH -#include +#include namespace SDL2pp { diff --git a/SDL2pp/libcpp_optional.hh b/SDL2pp/external/libcpp_optional.hh similarity index 100% rename from SDL2pp/libcpp_optional.hh rename to SDL2pp/external/libcpp_optional.hh From 76f2d746ca507ccda0d0ccc82079533fd300625e Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Thu, 25 Dec 2014 19:41:32 +0300 Subject: [PATCH 9/9] Add Optional to library headers --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d3fe76..97e6735 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ SET(LIBRARY_HEADERS SDL2pp/AudioSpec.hh SDL2pp/ContainerRWops.hh SDL2pp/Exception.hh + SDL2pp/Optional.hh SDL2pp/Point.hh SDL2pp/RWops.hh SDL2pp/Rect.hh