diff options
86 files changed, 8469 insertions, 52 deletions
diff --git a/libcxx/.gitignore b/libcxx/.gitignore index db7f90d..49657ed 100644 --- a/libcxx/.gitignore +++ b/libcxx/.gitignore @@ -56,3 +56,6 @@ target/ # MSVC libraries test harness env.lst keep.lst + +# Editor by-products +.vscode/ diff --git a/libcxx/include/__config b/libcxx/include/__config index db55b2c..b18bd46 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -914,6 +914,10 @@ extern "C" void __sanitizer_annotate_contiguous_container( #define _LIBCPP_SAFE_STATIC #endif +#if !__has_builtin(__builtin_addressof) && _GNUC_VER < 700 +#define _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF +#endif + #endif // __cplusplus #endif // _LIBCPP_CONFIG diff --git a/libcxx/include/optional b/libcxx/include/optional new file mode 100644 index 0000000..46252c7 --- /dev/null +++ b/libcxx/include/optional @@ -0,0 +1,1313 @@ +// -*- 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++1z + +namespace std { + // 20.6.3, optional for object types + template <class T> class optional; + + // 20.6.4, no-value state indicator + struct nullopt_t{see below }; + constexpr nullopt_t nullopt(unspecified ); + + // 20.6.5, class bad_optional_access + class bad_optional_access; + + // 20.6.6, 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>&); + 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; + + // 20.6.8, 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>&); + + // 20.6.9, specialized algorithms + template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below ); + template <class T> constexpr optional<see below > make_optional(T&&); + template <class T, class... Args> + constexpr optional<T> make_optional(Args&&... args); + template <class T, class U, class... Args> + constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); + + // 20.6.10, hash support + template <class T> struct hash; + template <class T> struct hash<optional<T>>; + + template <class T> class optional { + public: + using value_type = T; + + // 20.6.3.1, constructors + constexpr optional() noexcept; + constexpr optional(nullopt_t) noexcept; + optional(const optional &); + optional(optional &&) noexcept(see below ); + 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 &&...); + template <class U = T> + constexpr EXPLICIT optional(U &&); + template <class U> + constexpr EXPLICIT optional(const optional<U> &); + template <class U> + constexpr EXPLICIT optional(optional<U> &&); + + // 20.6.3.2, destructor + ~optional(); + + // 20.6.3.3, assignment + optional &operator=(nullopt_t) noexcept; + optional &operator=(const optional &); + optional &operator=(optional &&) noexcept(see below ); + template <class U = T> optional &operator=(U &&); + template <class U> optional &operator=(const optional<U> &); + template <class U> optional &operator=(optional<U> &&); + template <class... Args> void emplace(Args &&...); + template <class U, class... Args> + void emplace(initializer_list<U>, Args &&...); + + // 20.6.3.4, swap + void swap(optional &) noexcept(see below ); + + // 20.6.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 bool has_value() 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 &&) &&; + + // 20.6.3.6, modifiers + void reset() noexcept; + + private: + T *val; // exposition only + }; +} // namespace std + +*/ + +#include <__config> +#include <__debug> +#include <__functional_base> +#include <__undef_min_max> +#include <functional> +#include <initializer_list> +#include <new> +#include <stdexcept> +#include <type_traits> +#include <utility> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +namespace std // purposefully not using versioning namespace +{ + +class _LIBCPP_EXCEPTION_ABI bad_optional_access + : public logic_error +{ +public: + _LIBCPP_INLINE_VISIBILITY + bad_optional_access() : logic_error("bad optional access") {} + + // Get the key function ~bad_optional_access() into the dylib + _LIBCPP_FUNC_VIS + virtual ~bad_optional_access() _NOEXCEPT; +}; + +} // std + +#if _LIBCPP_STD_VER > 14 + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_NORETURN +inline _LIBCPP_INLINE_VISIBILITY +void __throw_bad_optional_access() { +#ifndef _LIBCPP_NO_EXCEPTIONS + throw bad_optional_access(); +#else + _VSTD::abort(); +#endif +} + +struct nullopt_t +{ + struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; }; + _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {} +}; + +/* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}}; + +template <class _Tp, bool = is_trivially_destructible<_Tp>::value> +struct __optional_destruct_base; + +template <class _Tp> +struct __optional_destruct_base<_Tp, false> +{ + typedef _Tp value_type; + static_assert(is_object_v<value_type>, + "instantiation of optional with a non-object type is undefined behavior"); + union + { + char __null_state_; + value_type __val_; + }; + bool __engaged_; + + _LIBCPP_INLINE_VISIBILITY + ~__optional_destruct_base() + { + if (__engaged_) + __val_.~value_type(); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_destruct_base() noexcept + : __null_state_(), + __engaged_(false) {} + + template <class... _Args> + _LIBCPP_INLINE_VISIBILITY + constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) + : __val_(_VSTD::forward<_Args>(__args)...), + __engaged_(true) {} + + _LIBCPP_INLINE_VISIBILITY + void reset() noexcept + { + if (__engaged_) + { + __val_.~value_type(); + __engaged_ = false; + } + } +}; + +template <class _Tp> +struct __optional_destruct_base<_Tp, true> +{ + typedef _Tp value_type; + static_assert(is_object_v<value_type>, + "instantiation of optional with a non-object type is undefined behavior"); + union + { + char __null_state_; + value_type __val_; + }; + bool __engaged_; + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_destruct_base() noexcept + : __null_state_(), + __engaged_(false) {} + + template <class... _Args> + _LIBCPP_INLINE_VISIBILITY + constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args) + : __val_(_VSTD::forward<_Args>(__args)...), + __engaged_(true) {} + + _LIBCPP_INLINE_VISIBILITY + void reset() noexcept + { + if (__engaged_) + { + __engaged_ = false; + } + } +}; + +template <class _Tp, bool = is_reference<_Tp>::value> +struct __optional_storage_base : __optional_destruct_base<_Tp> +{ + using __base = __optional_destruct_base<_Tp>; + using value_type = _Tp; + using __base::__base; + + _LIBCPP_INLINE_VISIBILITY + constexpr bool has_value() const noexcept + { + return this->__engaged_; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type& __get() & noexcept + { + return this->__val_; + } + _LIBCPP_INLINE_VISIBILITY + constexpr const value_type& __get() const& noexcept + { + return this->__val_; + } + _LIBCPP_INLINE_VISIBILITY + constexpr value_type&& __get() && noexcept + { + return _VSTD::move(this->__val_); + } + _LIBCPP_INLINE_VISIBILITY + constexpr const value_type&& __get() const&& noexcept + { + return _VSTD::move(this->__val_); + } + + template <class... _Args> + _LIBCPP_INLINE_VISIBILITY + void __construct(_Args&&... __args) + { + _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); + ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); + this->__engaged_ = true; + } + + template <class _That> + _LIBCPP_INLINE_VISIBILITY + void __construct_from(_That&& __opt) + { + if (__opt.has_value()) + __construct(_VSTD::forward<_That>(__opt).__get()); + } + + template <class _That> + _LIBCPP_INLINE_VISIBILITY + void __assign_from(_That&& __opt) + { + if (this->__engaged_ == __opt.has_value()) + { + if (this->__engaged_) + this->__val_ = _VSTD::forward<_That>(__opt).__get(); + } + else + { + if (this->__engaged_) + this->reset(); + else + __construct(_VSTD::forward<_That>(__opt).__get()); + } + } +}; + +// optional<T&> is currently required ill-formed, however it may to be in the +// future. For this reason it has already been implemented to ensure we can +// make the change in an ABI compatible manner. +template <class _Tp> +struct __optional_storage_base<_Tp, true> +{ + using value_type = _Tp; + using __raw_type = remove_reference_t<_Tp>; + __raw_type* __value_; + + template <class _Up> + static constexpr bool __can_bind_reference() { + using _RawUp = typename remove_reference<_Up>::type; + using _UpPtr = _RawUp*; + using _RawTp = typename remove_reference<_Tp>::type; + using _TpPtr = _RawTp*; + using _CheckLValueArg = integral_constant<bool, + (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value) + || is_same<_RawUp, reference_wrapper<_RawTp>>::value + || is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value + >; + return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value) + || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value && + is_convertible<_UpPtr, _TpPtr>::value); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr __optional_storage_base() noexcept + : __value_(nullptr) {} + + template <class _UArg> + _LIBCPP_INLINE_VISIBILITY + constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) + : __value_(_VSTD::addressof(__uarg)) + { + static_assert(__can_bind_reference<_UArg>(), + "Attempted to construct a reference element in tuple from a " + "possible temporary"); + } + + _LIBCPP_INLINE_VISIBILITY + void reset() noexcept { __value_ = nullptr; } + + _LIBCPP_INLINE_VISIBILITY + constexpr bool has_value() const noexcept + { return __value_ != nullptr; } + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type& __get() const& noexcept + { return *__value_; } + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type&& __get() const&& noexcept + { return _VSTD::forward<value_type>(*__value_); } + + template <class _UArg> + _LIBCPP_INLINE_VISIBILITY + void __construct(_UArg&& __val) + { + _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage"); + static_assert(__can_bind_reference<_UArg>(), + "Attempted to construct a reference element in tuple from a " + "possible temporary"); + __value_ = _VSTD::addressof(__val); + } + + template <class _That> + _LIBCPP_INLINE_VISIBILITY + void __construct_from(_That&& __opt) + { + if (__opt.has_value()) + __construct(_VSTD::forward<_That>(__opt).__get()); + } + + template <class _That> + _LIBCPP_INLINE_VISIBILITY + void __assign_from(_That&& __opt) + { + if (has_value() == __opt.has_value()) + { + if (has_value()) + *__value_ = _VSTD::forward<_That>(__opt).__get(); + } + else + { + if (has_value()) + reset(); + else + __construct(_VSTD::forward<_That>(__opt).__get()); + } + } +}; + +template <class _Tp, bool = is_trivially_copyable<_Tp>::value> +struct __optional_storage; + +template <class _Tp> +struct __optional_storage<_Tp, true> : __optional_storage_base<_Tp> +{ + using __optional_storage_base<_Tp>::__optional_storage_base; +}; + +template <class _Tp> +struct __optional_storage<_Tp, false> : __optional_storage_base<_Tp> +{ + using value_type = _Tp; + using __optional_storage_base<_Tp>::__optional_storage_base; + + _LIBCPP_INLINE_VISIBILITY + __optional_storage() = default; + + _LIBCPP_INLINE_VISIBILITY + __optional_storage(const __optional_storage& __opt) + { + this->__construct_from(__opt); + } + + _LIBCPP_INLINE_VISIBILITY + __optional_storage(__optional_storage&& __opt) + noexcept(is_nothrow_move_constructible_v<value_type>) + { + this->__construct_from(_VSTD::move(__opt)); + } + + _LIBCPP_INLINE_VISIBILITY + __optional_storage& operator=(const __optional_storage& __opt) + { + this->__assign_from(__opt); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __optional_storage& operator=(__optional_storage&& __opt) + noexcept(is_nothrow_move_assignable_v<value_type> && + is_nothrow_move_constructible_v<value_type>) + { + this->__assign_from(_VSTD::move(__opt)); + return *this; + } +}; + +template <class _Tp> +using __optional_sfinae_ctor_base_t = __sfinae_ctor_base< + is_copy_constructible<_Tp>::value, + is_move_constructible<_Tp>::value +>; + +template <class _Tp> +using __optional_sfinae_assign_base_t = __sfinae_assign_base< + (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value), + (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) +>; + +template <class _Tp> +class optional + : private __optional_storage<_Tp> + , private __optional_sfinae_ctor_base_t<_Tp> + , private __optional_sfinae_assign_base_t<_Tp> +{ + using __base = __optional_storage<_Tp>; +public: + using value_type = _Tp; + +private: + // Disable the reference extension using this static assert. + static_assert(!is_same_v<value_type, in_place_t>, + "instantiation of optional with in_place_t is ill-formed"); + static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>, + "instantiation of optional with nullopt_t is ill-formed"); + static_assert(!is_reference_v<value_type>, + "instantiation of optional with a reference type is ill-formed"); + static_assert(is_destructible_v<value_type>, + "instantiation of optional with a non-destructible type is ill-formed"); + + // LWG2756: conditionally explicit conversion from _Up + struct _CheckOptionalArgsConstructor { + template <class _Up> + static constexpr bool __enable_implicit() { + return is_constructible_v<_Tp, _Up&&> && + is_convertible_v<_Up&&, _Tp>; + } + + template <class _Up> + static constexpr bool __enable_explicit() { + return is_constructible_v<_Tp, _Up&&> && + !is_convertible_v<_Up&&, _Tp>; + } + }; + template <class _Up> + using _CheckOptionalArgsCtor = conditional_t< + !is_same_v<in_place_t, _Up> && + !is_same_v<decay_t<_Up>, optional>, + _CheckOptionalArgsConstructor, + __check_tuple_constructor_fail + >; + template <class _QualUp> + struct _CheckOptionalLikeConstructor { + template <class _Up, class _Opt = optional<_Up>> + using __check_constructible_from_opt = __lazy_or< + is_constructible<_Tp, _Opt&>, + is_constructible<_Tp, _Opt const&>, + is_constructible<_Tp, _Opt&&>, + is_constructible<_Tp, _Opt const&&>, + is_convertible<_Opt&, _Tp>, + is_convertible<_Opt const&, _Tp>, + is_convertible<_Opt&&, _Tp>, + is_convertible<_Opt const&&, _Tp> + >; + template <class _Up, class _Opt = optional<_Up>> + using __check_assignable_from_opt = __lazy_or< + is_assignable<_Tp&, _Opt&>, + is_assignable<_Tp&, _Opt const&>, + is_assignable<_Tp&, _Opt&&>, + is_assignable<_Tp&, _Opt const&&> + >; + template <class _Up, class _QUp = _QualUp> + static constexpr bool __enable_implicit() { + return is_convertible<_QUp, _Tp>::value && + !__check_constructible_from_opt<_Up>::value; + } + template <class _Up, class _QUp = _QualUp> + static constexpr bool __enable_explicit() { + return !is_convertible<_QUp, _Tp>::value && + !__check_constructible_from_opt<_Up>::value; + } + template <class _Up, class _QUp = _QualUp> + static constexpr bool __enable_assign() { + // Construction and assignability of _Qup to _Tp has already been + // checked. + return !__check_constructible_from_opt<_Up>::value && + !__check_assignable_from_opt<_Up>::value; + } + }; + + template <class _Up, class _QualUp> + using _CheckOptionalLikeCtor = conditional_t< + __lazy_and< + __lazy_not<is_same<_Up, _Tp>>, + is_constructible<_Tp, _QualUp> + >::value, + _CheckOptionalLikeConstructor<_QualUp>, + __check_tuple_constructor_fail + >; + template <class _Up, class _QualUp> + using _CheckOptionalLikeAssign = conditional_t< + __lazy_and< + __lazy_not<is_same<_Up, _Tp>>, + is_constructible<_Tp, _QualUp>, + is_assignable<_Tp&, _QualUp> + >::value, + _CheckOptionalLikeConstructor<_QualUp>, + __check_tuple_constructor_fail + >; +public: + + _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} + _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default; + _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default; + _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} + + template <class... _Args, class = enable_if_t< + is_constructible_v<value_type, _Args...>> + > + _LIBCPP_INLINE_VISIBILITY + constexpr explicit optional(in_place_t, _Args&&... __args) + : __base(in_place, _VSTD::forward<_Args>(__args)...) {} + + template <class _Up, class... _Args, class = enable_if_t< + is_constructible_v<value_type, initializer_list<_Up>&, _Args...>> + > + _LIBCPP_INLINE_VISIBILITY + constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} + + template <class _Up = value_type, enable_if_t< + _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + constexpr optional(_Up&& __v) + : __base(in_place, _VSTD::forward<_Up>(__v)) {} + + template <class _Up, enable_if_t< + _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + constexpr explicit optional(_Up&& __v) + : __base(in_place, _VSTD::forward<_Up>(__v)) {} + + // LWG2756: conditionally explicit conversion from const optional<_Up>& + template <class _Up, enable_if_t< + _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + optional(const optional<_Up>& __v) + { + this->__construct_from(__v); + } + template <class _Up, enable_if_t< + _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + explicit optional(const optional<_Up>& __v) + { + this->__construct_from(__v); + } + + // LWG2756: conditionally explicit conversion from optional<_Up>&& + template <class _Up, enable_if_t< + _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + optional(optional<_Up>&& __v) + { + this->__construct_from(_VSTD::move(__v)); + } + template <class _Up, enable_if_t< + _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + explicit optional(optional<_Up>&& __v) + { + this->__construct_from(_VSTD::move(__v)); + } + + _LIBCPP_INLINE_VISIBILITY + optional& operator=(nullopt_t) noexcept + { + reset(); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default; + _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default; + + // LWG2756 + template <class _Up = value_type, + class = enable_if_t + < + !is_same_v<_Up, optional> && + !(is_same_v<_Up, value_type> && is_scalar_v<value_type>) && + is_constructible_v<value_type, _Up> && + is_assignable_v<value_type&, _Up> + > + > + _LIBCPP_INLINE_VISIBILITY + optional& + operator=(_Up&& __v) + { + if (this->has_value()) + this->__get() = _VSTD::forward<_Up>(__v); + else + this->__construct(_VSTD::forward<_Up>(__v)); + return *this; + } + + // LWG2756 + template <class _Up, enable_if_t< + _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + optional& + operator=(const optional<_Up>& __v) + { + this->__assign_from(__v); + return *this; + } + + // LWG2756 + template <class _Up, enable_if_t< + _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>() + , int> = 0> + _LIBCPP_INLINE_VISIBILITY + optional& + operator=(optional<_Up>&& __v) + { + this->__assign_from(_VSTD::move(__v)); + return *this; + } + + template <class... _Args, + class = enable_if_t + < + is_constructible_v<value_type, _Args...> + > + > + _LIBCPP_INLINE_VISIBILITY + void + emplace(_Args&&... __args) + { + reset(); + this->__construct(_VSTD::forward<_Args>(__args)...); + } + + template <class _Up, class... _Args, + class = enable_if_t + < + is_constructible_v<value_type, initializer_list<_Up>&, _Args...> + > + > + _LIBCPP_INLINE_VISIBILITY + void + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + reset(); + this->__construct(__il, _VSTD::forward<_Args>(__args)...); + } + + _LIBCPP_INLINE_VISIBILITY + void swap(optional& __opt) + noexcept(is_nothrow_move_constructible_v<value_type> && + is_nothrow_swappable_v<value_type>) + { + if (this->has_value() == __opt.has_value()) + { + using _VSTD::swap; + if (this->has_value()) + swap(this->__get(), __opt.__get()); + } + else + { + if (this->has_value()) + { + __opt.__construct(_VSTD::move(this->__get())); + reset(); + } + else + { + this->__construct(_VSTD::move(__opt.__get())); + __opt.reset(); + } + } + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + add_pointer_t<value_type const> + operator->() const + { + _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); +#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF + return _VSTD::addressof(this->__get()); +#else + return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); +#endif + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + add_pointer_t<value_type> + operator->() + { + _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value"); +#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF + return _VSTD::addressof(this->__get()); +#else + return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get()); +#endif + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + const value_type& + operator*() const& + { + _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); + return this->__get(); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + value_type& + operator*() & + { + _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); + return this->__get(); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + value_type&& + operator*() && + { + _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); + return _VSTD::move(this->__get()); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr + const value_type&& + operator*() const&& + { + _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value"); + return _VSTD::move(this->__get()); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr explicit operator bool() const noexcept { return has_value(); } + + using __base::has_value; + using __base::__get; + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type const& value() const& + { + if (!this->has_value()) + __throw_bad_optional_access(); + return this->__get(); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type& value() & + { + if (!this->has_value()) + __throw_bad_optional_access(); + return this->__get(); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type&& value() && + { + if (!this->has_value()) + __throw_bad_optional_access(); + return _VSTD::move(this->__get()); + } + + _LIBCPP_INLINE_VISIBILITY + constexpr value_type const&& value() const&& + { + if (!this->has_value()) + __throw_bad_optional_access(); + return _VSTD::move(this->__get()); + } + + template <class _Up> + _LIBCPP_INLINE_VISIBILITY + constexpr value_type value_or(_Up&& __v) const& + { + static_assert(is_copy_constructible_v<value_type>, + "optional<T>::value_or: T must be copy constructible"); + static_assert(is_convertible_v<_Up, value_type>, + "optional<T>::value_or: U must be convertible to T"); + return this->has_value() ? this->__get() : + static_cast<value_type>(_VSTD::forward<_Up>(__v)); + } + + template <class _Up> + _LIBCPP_INLINE_VISIBILITY + value_type value_or(_Up&& __v) && + { + static_assert(is_move_constructible_v<value_type>, + "optional<T>::value_or: T must be move constructible"); + static_assert(is_convertible_v<_Up, value_type>, + "optional<T>::value_or: U must be convertible to T"); + return this->has_value() ? _VSTD::move(this->__get()) : + static_cast<value_type>(_VSTD::forward<_Up>(__v)); + } + + using __base::reset; + +private: + template <class _Up> + _LIBCPP_INLINE_VISIBILITY + static _Up* + __operator_arrow(true_type, _Up& __x) + { + return _VSTD::addressof(__x); + } + + template <class _Up> + _LIBCPP_INLINE_VISIBILITY + static constexpr _Up* + __operator_arrow(false_type, _Up& __x) + { + return &__x; + } +}; + +// Comparisons between optionals +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator==(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (static_cast<bool>(__x) != static_cast<bool>(__y)) + return false; + if (!static_cast<bool>(__x)) + return true; + return *__x == *__y; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (static_cast<bool>(__x) != static_cast<bool>(__y)) + return true; + if (!static_cast<bool>(__x)) + return false; + return *__x != *__y; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator<(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (!static_cast<bool>(__y)) + return false; + if (!static_cast<bool>(__x)) + return true; + return *__x < *__y; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator>(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (!static_cast<bool>(__x)) + return false; + if (!static_cast<bool>(__y)) + return true; + return *__x > *__y; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (!static_cast<bool>(__x)) + return true; + if (!static_cast<bool>(__y)) + return false; + return *__x <= *__y; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y) +{ + if (!static_cast<bool>(__y)) + return true; + if (!static_cast<bool>(__x)) + return false; + return *__x >= *__y; +} + +// Comparisons with nullopt +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator==(const optional<_Tp>& __x, nullopt_t) noexcept +{ + return !static_cast<bool>(__x); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator==(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return !static_cast<bool>(__x); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator!=(const optional<_Tp>& __x, nullopt_t) noexcept +{ + return static_cast<bool>(__x); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator!=(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return static_cast<bool>(__x); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator<(const optional<_Tp>&, nullopt_t) noexcept +{ + return false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator<(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return static_cast<bool>(__x); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator<=(const optional<_Tp>& __x, nullopt_t) noexcept +{ + return !static_cast<bool>(__x); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator<=(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return true; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator>(const optional<_Tp>& __x, nullopt_t) noexcept +{ + return static_cast<bool>(__x); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator>(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator>=(const optional<_Tp>&, nullopt_t) noexcept +{ + return true; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +bool +operator>=(nullopt_t, const optional<_Tp>& __x) noexcept +{ + return !static_cast<bool>(__x); +} + +// Comparisons with T +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator==(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast<bool>(__x) ? *__x == __v : false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() == + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator==(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast<bool>(__x) ? __v == *__x : false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator!=(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast<bool>(__x) ? *__x != __v : true; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() != + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator!=(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast<bool>(__x) ? __v != *__x : true; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator<(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast<bool>(__x) ? *__x < __v : true; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() < + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator<(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast<bool>(__x) ? __v < *__x : false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator<=(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast<bool>(__x) ? *__x <= __v : true; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <= + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator<=(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast<bool>(__x) ? __v <= *__x : false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator>(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast<bool>(__x) ? *__x > __v : false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() > + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator>(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast<bool>(__x) ? __v > *__x : true; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator>=(const optional<_Tp>& __x, const _Tp& __v) +{ + return static_cast<bool>(__x) ? *__x >= __v : false; +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +enable_if_t< + is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >= + _VSTD::declval<const _Tp&>()), bool>, + bool +> +operator>=(const _Tp& __v, const optional<_Tp>& __x) +{ + return static_cast<bool>(__x) ? __v >= *__x : true; +} + + +template <class _Tp> +inline _LIBCPP_INLINE_VISIBILITY +enable_if_t< + is_move_constructible_v<_Tp> && is_swappable_v<_Tp>, + void +> +swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) +{ + __x.swap(__y); +} + +template <class _Tp> +_LIBCPP_INLINE_VISIBILITY constexpr +optional<decay_t<_Tp>> make_optional(_Tp&& __v) +{ + return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v)); +} + +template <class _Tp, class... _Args> +_LIBCPP_INLINE_VISIBILITY constexpr +optional<_Tp> make_optional(_Args&&... __args) +{ + return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...); +} + +template <class _Tp, class _Up, class... _Args> +_LIBCPP_INLINE_VISIBILITY constexpr +optional<_Tp> make_optional(initializer_list<_Up> __il, _Args&&... __args) +{ + return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...); +} + +template <class _Tp> +struct _LIBCPP_TYPE_VIS_ONLY hash<optional<_Tp> > +{ + typedef optional<_Tp> argument_type; + typedef size_t result_type; + + _LIBCPP_INLINE_VISIBILITY + result_type operator()(const argument_type& __opt) const _NOEXCEPT + { + return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0; + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 14 + +#endif // _LIBCPP_OPTIONAL diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 06ee3e7..43687a7 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -425,7 +425,7 @@ template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp #endif // addressof -#if __has_builtin(__builtin_addressof) || _GNUC_VER >= 700 +#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF template <class _Tp> inline _LIBCPP_CONSTEXPR_AFTER_CXX14 @@ -446,7 +446,7 @@ addressof(_Tp& __x) _NOEXCEPT return (_Tp*)&reinterpret_cast<const volatile char&>(__x); } -#endif // __has_builtin(__builtin_addressof) +#endif // _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF #if defined(_LIBCPP_HAS_OBJC_ARC) && !defined(_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF) // Objective-C++ Automatic Reference Counting uses qualified pointers diff --git a/libcxx/src/optional.cpp b/libcxx/src/optional.cpp index 8c5dd76..f2fbfdfe 100644 --- a/libcxx/src/optional.cpp +++ b/libcxx/src/optional.cpp @@ -7,18 +7,18 @@ // //===----------------------------------------------------------------------===// +#include "optional" #include "experimental/optional" -_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL +namespace std +{ -#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +bad_optional_access::~bad_optional_access() _NOEXCEPT = default; -bad_optional_access::~bad_optional_access() _NOEXCEPT {} +} // std -#else +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL bad_optional_access::~bad_optional_access() _NOEXCEPT = default; -#endif - _LIBCPP_END_NAMESPACE_EXPERIMENTAL diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp new file mode 100644 index 0000000..e4de92f --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional<T>& operator=(const optional<T>& rhs); + +#include <optional> +#include <string> +#include <type_traits> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y& operator=(const Y&) { return *this; } +}; + +struct Z1 +{ + Z1() = default; + Z1(Z1&&) = default; + Z1(const Z1&) = default; + Z1& operator=(Z1&&) = default; + Z1& operator=(const Z1&) = delete; +}; + +struct Z2 +{ + Z2() = default; + Z2(Z2&&) = default; + Z2(const Z2&) = delete; + Z2& operator=(Z2&&) = default; + Z2& operator=(const Z2&) = default; +}; + +#if __cplusplus >= 201402 +template <class T> +constexpr bool +test() +{ + optional<T> opt; + optional<T> opt2; + opt = opt2; + return true; +} +#endif + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_assignable<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + { + using T = X; + static_assert((std::is_trivially_copy_assignable<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + static_assert(!(std::is_trivially_copy_assignable<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_copy_assignable<optional<std::string>>::value), ""); + + static_assert(!(std::is_copy_assignable<optional<Z1>>::value), ""); + static_assert(!(std::is_copy_assignable<optional<Z2>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp new file mode 100644 index 0000000..e2eaa8c --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional<T>& operator=(optional<T>&& rhs); + +#include <optional> +#include <string> +#include <type_traits> +#include <utility> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y& operator=(Y&&) { return *this; } +}; + +struct Z1 +{ + Z1() = default; + Z1(Z1&&) = default; + Z1& operator=(Z1&&) = delete; +}; + +struct Z2 +{ + Z2() = default; + Z2(Z2&&) = delete; + Z2& operator=(Z2&&) = default; +}; + +#if __cplusplus >= 201402 +template <class T> +constexpr bool +test() +{ + optional<T> opt; + optional<T> opt2; + opt = std::move(opt2); + return true; +} +#endif + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); +#if __cplusplus >= 201402 + static_assert(test<T>(), ""); +#endif + } + static_assert(!(std::is_trivially_move_assignable<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_move_assignable<optional<std::string>>::value), ""); + + static_assert(!(std::is_move_assignable<optional<Z1>>::value), ""); + static_assert(!(std::is_move_assignable<optional<Z2>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp new file mode 100644 index 0000000..75e7635 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional(const optional<T>& rhs); + +#include <optional> +#include <string> +#include <type_traits> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y(const Y&) {} +}; + +struct Z +{ + Z() = default; + Z(Z&&) = delete; + Z(const Z&) = delete; + Z& operator=(Z&&) = delete; + Z& operator=(const Z&) = delete; +}; + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = opt; + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = opt; + (void)opt2; + } + static_assert(!(std::is_trivially_copy_constructible<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_copy_constructible<optional<std::string>>::value), ""); + + static_assert(!(std::is_copy_constructible<optional<Z>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp new file mode 100644 index 0000000..e6d9bb8 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-exceptions +// <optional> + +// optional(optional<T>&& rhs); + +#include <optional> +#include <string> +#include <type_traits> +#include <utility> + +using std::optional; + +struct X {}; + +struct Y +{ + Y() = default; + Y(Y&&) {} +}; + +struct Z +{ + Z() = default; + Z(Z&&) = delete; + Z(const Z&) = delete; + Z& operator=(Z&&) = delete; + Z& operator=(const Z&) = delete; +}; + +int main() +{ + { + using T = int; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = std::move(opt); + (void)opt2; + } + { + using T = X; + static_assert((std::is_trivially_copy_constructible<optional<T>>::value), ""); + constexpr optional<T> opt; + constexpr optional<T> opt2 = std::move(opt); + (void)opt2; + } + static_assert(!(std::is_trivially_move_constructible<optional<Y>>::value), ""); + static_assert(!(std::is_trivially_move_constructible<optional<std::string>>::value), ""); + + static_assert(!(std::is_move_constructible<optional<Z>>::value), ""); +} diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp new file mode 100644 index 0000000..9493d6b --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "archetypes.hpp" + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + template <template <class> class TestMF> + static constexpr bool check_same() { + return TestMF<O>::value == TestMF<T>::value; + } + + // Test that optional inherits the correct trivial/non-trivial members + static_assert(check_same<std::is_trivially_destructible>(), ""); + static_assert(check_same<std::is_trivially_copyable>(), ""); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +struct TrivialMoveNonTrivialCopy { + TrivialMoveNonTrivialCopy() = default; + TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} + TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; + TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } + TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; +}; + +struct TrivialCopyNonTrivialMove { + TrivialCopyNonTrivialMove() = default; + TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} + TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } +}; + +int main() +{ + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, + DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} + ); +} diff --git a/libcxx/test/libcxx/utilities/optional/version.pass.cpp b/libcxx/test/libcxx/utilities/optional/version.pass.cpp new file mode 100644 index 0000000..e7581b5 --- /dev/null +++ b/libcxx/test/libcxx/utilities/optional/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <optional> + +#include <optional> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp index 408231f..b23a5e4 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp @@ -59,7 +59,7 @@ int main() !std::is_nothrow_swappable_with<A&, A&>::value, ""); } { - // test that hetrogenius swap is allowed only if both 'swap(A, B)' and + // test that heterogeneous swap is allowed only if both 'swap(A, B)' and // 'swap(B, A)' are valid. static_assert(std::is_nothrow_swappable_with<A&, B&>::value, ""); static_assert(!std::is_nothrow_swappable_with<A&, C&>::value && diff --git a/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp new file mode 100644 index 0000000..e3c7bb5 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// class bad_optional_access is default constructible + +#include <optional> +#include <type_traits> + +int main() +{ + using std::bad_optional_access; + bad_optional_access ex; +} diff --git a/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp b/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp new file mode 100644 index 0000000..85e36d2 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// class bad_optional_access : public logic_error + +#include <optional> +#include <type_traits> + +int main() +{ + using std::bad_optional_access; + + static_assert(std::is_base_of<std::logic_error, bad_optional_access>::value, ""); + static_assert(std::is_convertible<bad_optional_access*, std::logic_error*>::value, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp new file mode 100644 index 0000000..b54a08f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator==(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator==(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator == ( const X &lhs, const X &rhs ) + { return lhs.i_ == rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 == T(1)), "" ); + static_assert ( (o2 == T(1)), "" ); + static_assert ( !(o3 == T(1)), "" ); + static_assert ( (o3 == T(2)), "" ); + static_assert ( (o3 == val), "" ); + + static_assert ( !(T(1) == o1), "" ); + static_assert ( (T(1) == o2), "" ); + static_assert ( !(T(1) == o3), "" ); + static_assert ( (T(2) == o3), "" ); + static_assert ( (val == o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp new file mode 100644 index 0000000..064114f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator>(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator > ( const X &lhs, const X &rhs ) + { return lhs.i_ > rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 > T(1)), "" ); + static_assert ( !(o2 > T(1)), "" ); // equal + static_assert ( (o3 > T(1)), "" ); + static_assert ( !(o2 > val), "" ); + static_assert ( !(o3 > val), "" ); // equal + static_assert ( !(o3 > T(3)), "" ); + + static_assert ( (T(1) > o1), "" ); + static_assert ( !(T(1) > o2), "" ); // equal + static_assert ( !(T(1) > o3), "" ); + static_assert ( (val > o2), "" ); + static_assert ( !(val > o3), "" ); // equal + static_assert ( (T(3) > o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp new file mode 100644 index 0000000..663686c --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator>=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator >= ( const X &lhs, const X &rhs ) + { return lhs.i_ >= rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( !(o1 >= T(1)), "" ); + static_assert ( (o2 >= T(1)), "" ); // equal + static_assert ( (o3 >= T(1)), "" ); + static_assert ( !(o2 >= val), "" ); + static_assert ( (o3 >= val), "" ); // equal + static_assert ( !(o3 >= T(3)), "" ); + + static_assert ( (T(1) >= o1), "" ); + static_assert ( (T(1) >= o2), "" ); // equal + static_assert ( !(T(1) >= o3), "" ); + static_assert ( (val >= o2), "" ); + static_assert ( (val >= o3), "" ); // equal + static_assert ( (T(3) >= o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp new file mode 100644 index 0000000..05ac5eb --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator<=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator <= ( const X &lhs, const X &rhs ) + { return lhs.i_ <= rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 <= T(1)), "" ); + static_assert ( (o2 <= T(1)), "" ); // equal + static_assert ( !(o3 <= T(1)), "" ); + static_assert ( (o2 <= val), "" ); + static_assert ( (o3 <= val), "" ); // equal + static_assert ( (o3 <= T(3)), "" ); + + static_assert ( !(T(1) <= o1), "" ); + static_assert ( (T(1) <= o2), "" ); // equal + static_assert ( (T(1) <= o3), "" ); + static_assert ( !(val <= o2), "" ); + static_assert ( (val <= o3), "" ); // equal + static_assert ( !(T(3) <= o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp new file mode 100644 index 0000000..d1891a2 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator<(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator < ( const X &lhs, const X &rhs ) + { return lhs.i_ < rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 < T(1)), "" ); + static_assert ( !(o2 < T(1)), "" ); // equal + static_assert ( !(o3 < T(1)), "" ); + static_assert ( (o2 < val), "" ); + static_assert ( !(o3 < val), "" ); // equal + static_assert ( (o3 < T(3)), "" ); + + static_assert ( !(T(1) < o1), "" ); + static_assert ( !(T(1) < o2), "" ); // equal + static_assert ( (T(1) < o3), "" ); + static_assert ( !(val < o2), "" ); + static_assert ( !(val < o3), "" ); // equal + static_assert ( !(T(3) < o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp new file mode 100644 index 0000000..ae2ff80 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator!=(const optional<T>& x, const T& v); +// template <class T> constexpr bool operator!=(const T& v, const optional<T>& x); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator != ( const X &lhs, const X &rhs ) + { return lhs.i_ != rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr T val(2); + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + constexpr O o3{val}; // engaged + + static_assert ( (o1 != T(1)), "" ); + static_assert ( !(o2 != T(1)), "" ); + static_assert ( (o3 != T(1)), "" ); + static_assert ( !(o3 != T(2)), "" ); + static_assert ( !(o3 != val), "" ); + + static_assert ( (T(1) != o1), "" ); + static_assert ( !(T(1) != o2), "" ); + static_assert ( (T(1) != o3), "" ); + static_assert ( !(T(2) != o3), "" ); + static_assert ( !(val != o3), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp b/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp new file mode 100644 index 0000000..dfdd07d --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> struct hash<optional<T>>; + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + + +int main() +{ + using std::optional; + const std::size_t nullopt_hash = + std::hash<optional<double>>{}(optional<double>{}); + + { + typedef int T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = 2; + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } + { + typedef std::string T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = std::string("123"); + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } + { + typedef std::unique_ptr<int> T; + optional<T> opt; + assert(std::hash<optional<T>>{}(opt) == nullopt_hash); + opt = std::unique_ptr<int>(new int(3)); + assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt)); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp new file mode 100644 index 0000000..a87a87f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt == o1), "" ); + static_assert ( !(nullopt == o2), "" ); + static_assert ( (o1 == nullopt), "" ); + static_assert ( !(o2 == nullopt), "" ); + + static_assert (noexcept(nullopt == o1), ""); + static_assert (noexcept(o1 == nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp new file mode 100644 index 0000000..3986a0a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt > o1), "" ); + static_assert ( !(nullopt > o2), "" ); + static_assert ( !(o1 > nullopt), "" ); + static_assert ( (o2 > nullopt), "" ); + + static_assert (noexcept(nullopt > o1), ""); + static_assert (noexcept(o1 > nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp new file mode 100644 index 0000000..9f24272 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt >= o1), "" ); + static_assert ( !(nullopt >= o2), "" ); + static_assert ( (o1 >= nullopt), "" ); + static_assert ( (o2 >= nullopt), "" ); + + static_assert (noexcept(nullopt >= o1), ""); + static_assert (noexcept(o1 >= nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp new file mode 100644 index 0000000..8e73247 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( (nullopt <= o1), "" ); + static_assert ( (nullopt <= o2), "" ); + static_assert ( (o1 <= nullopt), "" ); + static_assert ( !(o2 <= nullopt), "" ); + + static_assert (noexcept(nullopt <= o1), ""); + static_assert (noexcept(o1 <= nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp new file mode 100644 index 0000000..39a8e4a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt < o1), "" ); + static_assert ( (nullopt < o2), "" ); + static_assert ( !(o1 < nullopt), "" ); + static_assert ( !(o2 < nullopt), "" ); + + static_assert (noexcept(nullopt < o1), ""); + static_assert (noexcept(o1 < nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp new file mode 100644 index 0000000..1c96dd4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept; +// template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept; + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + { + typedef int T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2{1}; // engaged + + static_assert ( !(nullopt != o1), "" ); + static_assert ( (nullopt != o2), "" ); + static_assert ( !(o1 != nullopt), "" ); + static_assert ( (o2 != nullopt), "" ); + + static_assert (noexcept(nullopt != o1), ""); + static_assert (noexcept(o1 != nullopt), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp new file mode 100644 index 0000000..86da5054 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// struct nullopt_t{see below}; + +#include <optional> + +using std::optional; +using std::nullopt_t; + +int main() +{ + // I roughly interpret LWG2736 as "it shall not be possible to copy-list-initialize nullopt_t with an + // empty braced-init-list." + nullopt_t foo = {}; +} diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp new file mode 100644 index 0000000..84bb29f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// struct nullopt_t{see below}; +// constexpr nullopt_t nullopt(unspecified); + +#include <optional> +#include <type_traits> + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +constexpr +int +test(const nullopt_t&) +{ + return 3; +} + +int main() +{ + static_assert((std::is_class<nullopt_t>::value), ""); + static_assert((std::is_empty<nullopt_t>::value), ""); + static_assert((std::is_literal_type<nullopt_t>::value), ""); + static_assert((!std::is_default_constructible<nullopt_t>::value), ""); + + static_assert(test(nullopt) == 3, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp new file mode 100644 index 0000000..6abdd0d --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp @@ -0,0 +1,261 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> optional<T>& operator=(U&& v); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct ThrowAssign { + static int dtor_called; + ThrowAssign() = default; + ThrowAssign(int) { TEST_THROW(42); } + ThrowAssign& operator=(int) { + TEST_THROW(42); + } + ~ThrowAssign() { ++dtor_called; } +}; +int ThrowAssign::dtor_called = 0; + +template <class T, class Arg = T, bool Expect = true> +void assert_assignable() { + static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, ""); + static_assert(!std::is_assignable<const optional<T>&, Arg>::value, ""); +} + +struct MismatchType { + explicit MismatchType(int) {} + explicit MismatchType(char*) {} + explicit MismatchType(int*) = delete; + MismatchType& operator=(int) { return *this; } + MismatchType& operator=(int*) { return *this; } + MismatchType& operator=(char*) = delete; +}; + +void test_sfinae() { + using I = TestTypes::TestType; + using E = ExplicitTestTypes::TestType; + assert_assignable<int>(); + assert_assignable<int, int&>(); + assert_assignable<int, int const&>(); + // Implicit test type + assert_assignable<I, I const&>(); + assert_assignable<I, I&&>(); + assert_assignable<I, int>(); + assert_assignable<I, void*, false>(); + // Explicit test type + assert_assignable<E, E const&>(); + assert_assignable<E, E &&>(); + assert_assignable<E, int>(); + assert_assignable<E, void*, false>(); + // Mismatch type + assert_assignable<MismatchType, int>(); + assert_assignable<MismatchType, int*, false>(); + assert_assignable<MismatchType, char*, false>(); +} + +void test_with_test_type() +{ + using T = TestTypes::TestType; + T::reset(); + { // to empty + optional<T> opt; + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(42); + T::reset_constructors(); + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 1); + assert(T::move_assigned == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {}; + assert(static_cast<bool>(opt) == false); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + } +} + +template <class T, class Value = int> +void test_with_type() { + { // to empty + optional<T> opt; + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(Value(42)); + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test const + optional<T> opt(Value(42)); + const T t(Value(3)); + opt = t; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + opt = {Value(1)}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(Value(42)); + opt = {}; + assert(static_cast<bool>(opt) == false); + } +} + +template <class T> +void test_with_type_multi() { + test_with_type<T>(); + { // test default argument + optional<T> opt; + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } +} + +void test_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using T = ThrowAssign; + { + using T = ThrowAssign; + optional<T> opt; + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == false); + } + assert(T::dtor_called == 0); + { + T::dtor_called = 0; + optional<T> opt(std::in_place); + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == true); + assert(T::dtor_called == 0); + } + assert(T::dtor_called == 1); +#endif +} + +enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 }; + +using Fn = void(*)(); + +int main() +{ + test_sfinae(); + // Test with instrumented type + test_with_test_type(); + // Test with various scalar types + test_with_type<int>(); + test_with_type<MyEnum, MyEnum>(); + test_with_type<int, MyEnum>(); + test_with_type<Fn, Fn>(); + // Test types with multi argument constructors + test_with_type_multi<ConstexprTestTypes::TestType>(); + test_with_type_multi<TrivialTestTypes::TestType>(); + // Test move only types + { + optional<std::unique_ptr<int>> opt; + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + { + optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2))); + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + test_throws(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp new file mode 100644 index 0000000..d471c05 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp @@ -0,0 +1,254 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// From LWG2451: +// template<class U> +// optional<T>& operator=(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(int) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +struct Y1 +{ + Y1() = default; + Y1(const int&) {} + Y1& operator=(const Y1&) = delete; +}; + +struct Y2 +{ + Y2() = default; + Y2(const int&) = delete; + Y2& operator=(const int&) { return *this; } +}; + +template <class T> +struct AssignableFrom { + static int type_constructed; + static int type_assigned; +static int int_constructed; + static int int_assigned; + + static void reset() { + type_constructed = int_constructed = 0; + type_assigned = int_assigned = 0; + } + + AssignableFrom() = default; + + explicit AssignableFrom(T) { ++type_constructed; } + AssignableFrom& operator=(T) { ++type_assigned; return *this; } + + AssignableFrom(int) { ++int_constructed; } + AssignableFrom& operator=(int) { ++int_assigned; return *this; } +private: + AssignableFrom(AssignableFrom const&) = delete; + AssignableFrom& operator=(AssignableFrom const&) = delete; +}; + +template <class T> int AssignableFrom<T>::type_constructed = 0; +template <class T> int AssignableFrom<T>::type_assigned = 0; +template <class T> int AssignableFrom<T>::int_constructed = 0; +template <class T> int AssignableFrom<T>::int_assigned = 0; + + +void test_with_test_type() { + using T = TestTypes::TestType; + T::reset(); + { // non-empty to empty + T::reset_constructors(); + optional<T> opt; + const optional<int> other(42); + opt = other; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // non-empty to non-empty + optional<T> opt(101); + const optional<int> other(42); + T::reset_constructors(); + opt = other; + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // empty to non-empty + optional<T> opt(101); + const optional<int> other; + T::reset_constructors(); + opt = other; + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); + { // empty to empty + optional<T> opt; + const optional<int> other; + T::reset_constructors(); + opt = other; + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); +} + +void test_ambigious_assign() { + using OptInt = std::optional<int>; + { + using T = AssignableFrom<OptInt const&>; + const OptInt a(42); + T::reset(); + { + std::optional<T> t; + t = a; + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + T::reset(); + { + std::optional<T> t(42); + t = a; + assert(T::type_constructed == 0); + assert(T::type_assigned == 1); + assert(T::int_constructed == 1); + assert(T::int_assigned == 0); + } + T::reset(); + { + std::optional<T> t(42); + t = std::move(a); + assert(T::type_constructed == 0); + assert(T::type_assigned == 1); + assert(T::int_constructed == 1); + assert(T::int_assigned == 0); + } + } + { + using T = AssignableFrom<OptInt&>; + OptInt a(42); + T::reset(); + { + std::optional<T> t; + t = a; + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(!std::is_assignable_v<Opt&, OptInt const&>, ""); + } + } +} + + +int main() +{ + test_with_test_type(); + test_ambigious_assign(); + { + optional<int> opt; + constexpr optional<short> opt2; + opt = opt2; + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + constexpr optional<short> opt2(short{2}); + opt = opt2; + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + constexpr optional<short> opt2; + opt = opt2; + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + constexpr optional<short> opt2(short{2}); + opt = opt2; + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<int> opt2(42); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = opt2; + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp new file mode 100644 index 0000000..98c90aa --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(const optional<T>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(const X&) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +template <class Tp> +constexpr bool assign_empty(optional<Tp>&& lhs) { + const optional<Tp> rhs; + lhs = rhs; + return !lhs.has_value() && !rhs.has_value(); +} + +template <class Tp> +constexpr bool assign_value(optional<Tp>&& lhs) { + const optional<Tp> rhs(101); + lhs = rhs; + return lhs.has_value() && rhs.has_value() && *lhs == *rhs; +} + +int main() +{ + { + using O = optional<int>; + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TrivialTestTypes::TestType>; + LIBCPP_STATIC_ASSERT(assign_empty(O{42}), ""); + LIBCPP_STATIC_ASSERT(assign_value(O{42}), ""); + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using O = optional<TestTypes::TestType>; + assert(assign_empty(O{42})); + assert(assign_value(O{42})); + } + { + using T = TestTypes::TestType; + T::reset(); + optional<T> opt(3); + const optional<T> opt2; + assert(T::alive == 1); + opt = opt2; + assert(T::alive == 0); + assert(!opt2.has_value()); + assert(!opt.has_value()); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<X> opt2(X{}); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = opt2; + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp new file mode 100644 index 0000000..be17aa6 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class... Args> void optional<T>::emplace(Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ +public: + static bool dtor_called; + Y() = default; + Y(int) { TEST_THROW(6);} + ~Y() {dtor_called = true;} +}; + +bool Y::dtor_called = false; + +template <class T> +void test_one_arg() { + using Opt = std::optional<T>; + { + Opt opt; + opt.emplace(); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(0)); + } + { + Opt opt; + opt.emplace(1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { + Opt opt(2); + opt.emplace(); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(0)); + } + { + Opt opt(2); + opt.emplace(1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } +} + + +template <class T> +void test_multi_arg() +{ + test_one_arg<T>(); + using Opt = std::optional<T>; + Opt opt; + { + opt.emplace(101, 41); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(101, 41)); + } + { + Opt opt; + opt.emplace({1, 2, 3, 4}); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // T sets its value to the size of the init list + } + { + Opt opt; + opt.emplace({1, 2, 3, 4, 5}, 6); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(5)); // T sets its value to the size of the init list + } +} + +template <class T> +void test_on_test_type() { + + T::reset(); + optional<T> opt; + assert(T::alive == 0); + { + T::reset_constructors(); + opt.emplace(); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::default_constructed == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T()); + } + { + T::reset_constructors(); + opt.emplace(); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::default_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T()); + } + { + T::reset_constructors(); + opt.emplace(101); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(101)); + } + { + T::reset_constructors(); + opt.emplace(-10, 99); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(-10, 99)); + } + { + T::reset_constructors(); + opt.emplace(-10, 99); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(-10, 99)); + } + { + T::reset_constructors(); + opt.emplace({-10, 99, 42, 1}); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // size of the initializer list + } + { + T::reset_constructors(); + opt.emplace({-10, 99, 42, 1}, 42); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(4)); // size of the initializer list + } +} + + + +int main() +{ + { + test_on_test_type<TestTypes::TestType>(); + test_on_test_type<ExplicitTestTypes::TestType>(); + } + { + using T = int; + test_one_arg<T>(); + test_one_arg<const T>(); + } + { + using T = ConstexprTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = ExplicitConstexprTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = TrivialTestTypes::TestType; + test_multi_arg<T>(); + } + { + using T = ExplicitTrivialTestTypes::TestType; + test_multi_arg<T>(); + } + { + optional<const int> opt; + opt.emplace(42); + assert(*opt == 42); + opt.emplace(); + assert(*opt == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + Y::dtor_called = false; + { + Y y; + optional<Y> opt(y); + try + { + assert(static_cast<bool>(opt) == true); + assert(Y::dtor_called == false); + opt.emplace(1); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + assert(Y::dtor_called == true); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp new file mode 100644 index 0000000..1c3c69a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U, class... Args> +// void optional<T>::emplace(initializer_list<U> il, Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <vector> + +#include "test_macros.h" + +using std::optional; + +class X +{ + int i_; + int j_ = 0; +public: + static bool dtor_called; + constexpr X() : i_(0) {} + constexpr X(int i) : i_(i) {} + constexpr X(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + ~X() {dtor_called = true;} + + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +bool X::dtor_called = false; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ + int i_; + int j_ = 0; +public: + static bool dtor_called; + Z() : i_(0) {} + Z(int i) : i_(i) {} + Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) + { TEST_THROW(6);} + ~Z() {dtor_called = true;} + + friend bool operator==(const Z& x, const Z& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +bool Z::dtor_called = false; + +int main() +{ + { + X x; + optional<X> opt(x); + assert(X::dtor_called == false); + opt.emplace({1, 2}); + assert(X::dtor_called == true); + assert(*opt == X({1, 2})); + } + { + optional<std::vector<int>> opt; + opt.emplace({1, 2, 3}, std::allocator<int>()); + assert(static_cast<bool>(opt) == true); + assert(*opt == std::vector<int>({1, 2, 3})); + } + { + optional<Y> opt; + opt.emplace({1, 2}); + assert(static_cast<bool>(opt) == true); + assert(*opt == Y({1, 2})); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + Z z; + optional<Z> opt(z); + try + { + assert(static_cast<bool>(opt) == true); + assert(Z::dtor_called == false); + opt.emplace({1, 2}); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + assert(Z::dtor_called == true); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp new file mode 100644 index 0000000..3ba261b --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp @@ -0,0 +1,174 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(optional<T>&& rhs) +// noexcept(is_nothrow_move_assignable<T>::value && +// is_nothrow_move_constructible<T>::value); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + static int alive; + + X() { ++alive; } + X(X&&) + { + if (throw_now) + TEST_THROW(6); + ++alive; + } + + X& operator=(X&&) + { + if (throw_now) + TEST_THROW(42); + return *this; + } + + ~X() { assert(alive > 0); --alive; } +}; + +struct Y {}; + +bool X::throw_now = false; +int X::alive = 0; + +int main() +{ + { + static_assert(std::is_nothrow_move_assignable<optional<int>>::value, ""); + optional<int> opt; + constexpr optional<int> opt2; + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + constexpr optional<int> opt2(2); + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + constexpr optional<int> opt2; + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == false, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + using T = TestTypes::TestType; + T::reset(); + optional<T> opt(3); + optional<T> opt2; + assert(T::alive == 1); + opt = std::move(opt2); + assert(T::alive == 0); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + constexpr optional<int> opt2(2); + opt = std::move(opt2); + static_assert(static_cast<bool>(opt2) == true, ""); + static_assert(*opt2 == 2, ""); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); + X::alive = 0; + X::throw_now = false; + optional<X> opt; + optional<X> opt2(X{}); + assert(X::alive == 1); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + assert(X::alive == 1); + } + assert(X::alive == 0); + { + static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, ""); + X::throw_now = false; + optional<X> opt(X{}); + optional<X> opt2(X{}); + assert(X::alive == 2); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 42); + assert(static_cast<bool>(opt) == true); + } + assert(X::alive == 2); + } + assert(X::alive == 0); +#endif // TEST_HAS_NO_EXCEPTIONS + { + static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, ""); + } + { + struct ThrowsMove { + ThrowsMove() noexcept {} + ThrowsMove(ThrowsMove const&) noexcept {} + ThrowsMove(ThrowsMove &&) noexcept(false) {} + ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; } + ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; } + }; + static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, ""); + struct ThrowsMoveAssign { + ThrowsMoveAssign() noexcept {} + ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {} + ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {} + ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; } + ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; } + }; + static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, ""); + struct NoThrowMove { + NoThrowMove() noexcept(false) {} + NoThrowMove(NoThrowMove const&) noexcept(false) {} + NoThrowMove(NoThrowMove &&) noexcept {} + NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; } + NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; } + }; + static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp new file mode 100644 index 0000000..991f433 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional<T>& operator=(nullopt_t) noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +int main() +{ + { + optional<int> opt; + static_assert(noexcept(opt = nullopt) == true, ""); + opt = nullopt; + assert(static_cast<bool>(opt) == false); + } + { + optional<int> opt(3); + opt = nullopt; + assert(static_cast<bool>(opt) == false); + } + using TT = TestTypes::TestType; + TT::reset(); + { + optional<TT> opt; + static_assert(noexcept(opt = nullopt) == true, ""); + assert(TT::destroyed == 0); + opt = nullopt; + assert(TT::constructed == 0); + assert(TT::alive == 0); + assert(TT::destroyed == 0); + assert(static_cast<bool>(opt) == false); + } + assert(TT::alive == 0); + assert(TT::destroyed == 0); + TT::reset(); + { + optional<TT> opt(42); + assert(TT::destroyed == 0); + TT::reset_constructors(); + opt = nullopt; + assert(TT::constructed == 0); + assert(TT::alive == 0); + assert(TT::destroyed == 1); + assert(static_cast<bool>(opt) == false); + } + assert(TT::alive == 0); + assert(TT::destroyed == 1); + TT::reset(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp new file mode 100644 index 0000000..db7fc19 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp @@ -0,0 +1,268 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// From LWG2451: +// template <class U> +// optional<T>& operator=(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <memory> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct X +{ + static bool throw_now; + + X() = default; + X(int &&) + { + if (throw_now) + TEST_THROW(6); + } +}; + +bool X::throw_now = false; + +struct Y1 +{ + Y1() = default; + Y1(const int&) {} + Y1& operator=(const Y1&) = delete; +}; + +struct Y2 +{ + Y2() = default; + Y2(const int&) = delete; + Y2& operator=(const int&) { return *this; } +}; + +class B {}; +class D : public B {}; + + +template <class T> +struct AssignableFrom { + static int type_constructed; + static int type_assigned; +static int int_constructed; + static int int_assigned; + + static void reset() { + type_constructed = int_constructed = 0; + type_assigned = int_assigned = 0; + } + + AssignableFrom() = default; + + explicit AssignableFrom(T) { ++type_constructed; } + AssignableFrom& operator=(T) { ++type_assigned; return *this; } + + AssignableFrom(int) { ++int_constructed; } + AssignableFrom& operator=(int) { ++int_assigned; return *this; } +private: + AssignableFrom(AssignableFrom const&) = delete; + AssignableFrom& operator=(AssignableFrom const&) = delete; +}; + +template <class T> int AssignableFrom<T>::type_constructed = 0; +template <class T> int AssignableFrom<T>::type_assigned = 0; +template <class T> int AssignableFrom<T>::int_constructed = 0; +template <class T> int AssignableFrom<T>::int_assigned = 0; + +void test_with_test_type() { + using T = TestTypes::TestType; + T::reset(); + { // non-empty to empty + T::reset_constructors(); + optional<T> opt; + optional<int> other(42); + opt = std::move(other); + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // non-empty to non-empty + optional<T> opt(101); + optional<int> other(42); + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == true); + assert(*other == 42); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(42)); + } + assert(T::alive == 0); + { // empty to non-empty + optional<T> opt(101); + optional<int> other; + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); + { // empty to empty + optional<T> opt; + optional<int> other; + T::reset_constructors(); + opt = std::move(other); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(other) == false); + assert(static_cast<bool>(opt) == false); + } + assert(T::alive == 0); +} + + +void test_ambigious_assign() { + using OptInt = std::optional<int>; + { + using T = AssignableFrom<OptInt&&>; + T::reset(); + { + OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, ""); + static_assert(!std::is_assignable<Opt&, const OptInt&>::value, ""); + static_assert(!std::is_assignable<Opt&, OptInt&>::value, ""); + } + } + { + using T = AssignableFrom<OptInt const&&>; + T::reset(); + { + const OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + T::reset(); + { + OptInt a(42); + std::optional<T> t; + t = std::move(a); + assert(T::type_constructed == 1); + assert(T::type_assigned == 0); + assert(T::int_constructed == 0); + assert(T::int_assigned == 0); + } + { + using Opt = std::optional<T>; + static_assert(std::is_assignable<Opt&, OptInt&&>::value, ""); + static_assert(!std::is_assignable<Opt&, const OptInt&>::value, ""); + static_assert(!std::is_assignable<Opt&, OptInt&>::value, ""); + } + } +} + + +int main() +{ + test_with_test_type(); + test_ambigious_assign(); + { + optional<int> opt; + optional<short> opt2; + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt; + optional<short> opt2(short{2}); + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<int> opt(3); + optional<short> opt2; + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == false); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + } + { + optional<int> opt(3); + optional<short> opt2(short{2}); + opt = std::move(opt2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + assert(static_cast<bool>(opt) == static_cast<bool>(opt2)); + assert(*opt == *opt2); + } + { + optional<std::unique_ptr<B>> opt; + optional<std::unique_ptr<D>> other(new D()); + opt = std::move(other); + assert(static_cast<bool>(opt) == true); + assert(static_cast<bool>(other) == true); + assert(opt->get() != nullptr); + assert(other->get() == nullptr); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + optional<int> opt2(42); + assert(static_cast<bool>(opt2) == true); + try + { + X::throw_now = true; + opt = std::move(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + assert(static_cast<bool>(opt) == false); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp new file mode 100644 index 0000000..18efd10 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp @@ -0,0 +1,137 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// template <class U> +// constexpr EXPLICIT optional(U&& u); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" +#include "test_convertible.hpp" + + +using std::optional; + +struct ImplicitThrow +{ + constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);} +}; + +struct ExplicitThrow +{ + constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);} +}; + + +template <class To, class From> +constexpr bool implicit_conversion(optional<To>&& opt, const From& v) +{ + using O = optional<To>; + static_assert(test_convertible<O, From>(), ""); + static_assert(!test_convertible<O, void*>(), ""); + static_assert(!test_convertible<O, From, int>(), ""); + return opt && *opt == static_cast<To>(v); +} + +template <class To, class Input, class Expect> +constexpr bool explicit_conversion(Input&& in, const Expect& v) +{ + using O = optional<To>; + static_assert(std::is_constructible<O, Input>::value, ""); + static_assert(!std::is_convertible<Input, O>::value, ""); + static_assert(!std::is_constructible<O, void*>::value, ""); + static_assert(!std::is_constructible<O, Input, int>::value, ""); + optional<To> opt(std::forward<Input>(in)); + return opt && *opt == static_cast<To>(v); +} + +void test_implicit() +{ + { + using T = long long; + static_assert(implicit_conversion<long long>(42, 42), ""); + } + { + using T = long double; + static_assert(implicit_conversion<long double>(3.14, 3.14), ""); + } + { + using T = TrivialTestTypes::TestType; + static_assert(implicit_conversion<T>(42, 42), ""); + } + { + using T = TestTypes::TestType; + assert(implicit_conversion<T>(3, T(3))); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try { + using T = ImplicitThrow; + optional<T> t = 42; + assert(false); + } catch (int) { + } + } +#endif +} + +void test_explicit() { + { + using T = ExplicitTrivialTestTypes::TestType; + using O = optional<T>; + static_assert(explicit_conversion<T>(42, 42), ""); + } + { + using T = ExplicitConstexprTestTypes::TestType; + using O = optional<T>; + static_assert(explicit_conversion<T>(42, 42), ""); + static_assert(!std::is_convertible<int, T>::value, ""); + } + { + using T = ExplicitTestTypes::TestType; + using O = optional<T>; + T::reset(); + { + assert(explicit_conversion<T>(42, 42)); + assert(T::alive == 0); + } + T::reset(); + { + optional<T> t(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::move_constructed == 0); + assert(T::copy_constructed == 0); + assert(t.value().value == 42); + } + assert(T::alive == 0); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try { + using T = ExplicitThrow; + optional<T> t(42); + assert(false); + } catch (int) { + } + } +#endif +} + +int main() { + test_implicit(); + test_explicit(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp new file mode 100644 index 0000000..3f98d90 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// constexpr optional(const T& v); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +int main() +{ + { + typedef int T; + constexpr T t(5); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } + { + typedef double T; + constexpr T t(3); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } + { + typedef TestTypes::TestType T; + T::reset(); + const T t(3); + optional<T> opt = t; + assert(T::alive == 2); + assert(T::copy_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ExplicitTestTypes::TestType T; + static_assert(!std::is_convertible<T const&, optional<T>>::value, ""); + T::reset(); + const T t(3); + optional<T> opt(t); + assert(T::alive == 2); + assert(T::copy_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ConstexprTestTypes::TestType T; + constexpr T t(3); + constexpr optional<T> opt = {t}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ExplicitConstexprTestTypes::TestType T; + static_assert(!std::is_convertible<const T&, optional<T>>::value, ""); + constexpr T t(3); + constexpr optional<T> opt(t); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + struct Z { + Z(int) {} + Z(const Z&) {throw 6;} + }; + typedef Z T; + try + { + const T t(3); + optional<T> opt(t); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp new file mode 100644 index 0000000..e12f6cb --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp @@ -0,0 +1,134 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// optional(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(const optional<U>& rhs, bool is_going_to_throw = false) +{ + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs = rhs; + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); +#endif +} + +class X +{ + int i_; +public: + X(int i) : i_(i) {} + X(const X& x) : i_(x.i_) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +class Y +{ + int i_; +public: + Y(int i) : i_(i) {} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {TEST_THROW(6);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} +}; + + +int main() +{ + { + typedef short U; + typedef int T; + optional<U> rhs; + test<T>(rhs); + } + { + typedef short U; + typedef int T; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs(U{3}); + test<T>(rhs, true); + } + + static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value), ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp new file mode 100644 index 0000000..d2b704c --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp @@ -0,0 +1,150 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional(const optional<T>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class T, class ...InitArgs> +void test(InitArgs&&... args) +{ + const optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *rhs); +} + +void test_throwing_ctor() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Z { + Z() : count(0) {} + Z(Z const& o) : count(o.count + 1) + { if (count == 2) throw 6; } + int count; + }; + const Z z; + const optional<Z> rhs(z); + try + { + optional<Z> lhs(rhs); + assert(false); + } + catch (int i) + { + assert(i == 6); + } +#endif +} + +template <class T, class ...InitArgs> +void test_ref(InitArgs&&... args) +{ + const optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = rhs; + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(&(*lhs) == &(*rhs)); +} + + +void test_reference_extension() +{ +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + using T = TestTypes::TestType; + T::reset(); + { + T t; + T::reset_constructors(); + test_ref<T&>(); + test_ref<T&>(t); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::destroyed == 1); + assert(T::alive == 0); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&>(); + test_ref<T const&>(t); + test_ref<T const&>(ct); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); + static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); + } +#endif +} + +int main() +{ + test<int>(); + test<int>(3); + { + using T = TestTypes::TestType; + T::reset(); + const optional<T> rhs; + assert(T::alive == 0); + const optional<T> lhs(rhs); + assert(lhs.has_value() == false); + assert(T::alive == 0); + } + TestTypes::TestType::reset(); + { + using T = TestTypes::TestType; + T::reset(); + const optional<T> rhs(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::copy_constructed == 0); + const optional<T> lhs(rhs); + assert(lhs.has_value()); + assert(T::copy_constructed == 1); + assert(T::alive == 2); + } + TestTypes::TestType::reset(); + { + using namespace ConstexprTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + using namespace TrivialTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + test_throwing_ctor(); + } + { + test_reference_extension(); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp new file mode 100644 index 0000000..62795b91 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr optional() noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class Opt> +void +test_constexpr() +{ + static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, ""); + + constexpr Opt opt; + static_assert(static_cast<bool>(opt) == false, ""); + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +template <class Opt> +void +test() +{ + static_assert(std::is_nothrow_default_constructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, ""); + { + Opt opt; + assert(static_cast<bool>(opt) == false); + } + { + const Opt opt; + assert(static_cast<bool>(opt) == false); + } + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +int main() +{ + test_constexpr<optional<int>>(); + test_constexpr<optional<int*>>(); + test_constexpr<optional<ImplicitTypes::NoCtors>>(); + test_constexpr<optional<NonTrivialTypes::NoCtors>>(); + test_constexpr<optional<NonConstexprTypes::NoCtors>>(); + test<optional<NonLiteralTypes::NoCtors>>(); + // EXTENSIONS +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + test_constexpr<optional<int&>>(); + test_constexpr<optional<const int&>>(); + test_constexpr<optional<int&>>(); + test_constexpr<optional<NonLiteralTypes::NoCtors&>>(); + test_constexpr<optional<NonLiteralTypes::NoCtors&&>>(); +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp new file mode 100644 index 0000000..64ac053 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// explicit optional(const optional<U>& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(const optional<U>& rhs, bool is_going_to_throw = false) +{ + static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), ""); + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs(rhs); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == T(*rhs)); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == T(*rhs)); +#endif +} + +class X +{ + int i_; +public: + explicit X(int i) : i_(i) {} + X(const X& x) : i_(x.i_) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +class Y +{ + int i_; +public: + explicit Y(int i) : i_(i) {} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ + int i_; +public: + explicit Z(int i) : i_(i) { TEST_THROW(6);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} +}; + + +int main() +{ + { + typedef X T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef X T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Y T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs; + test<T>(rhs); + } + { + typedef Z T; + typedef int U; + optional<U> rhs(3); + test<T>(rhs, true); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp new file mode 100644 index 0000000..2c6757a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// explicit optional(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(optional<U>&& rhs, bool is_going_to_throw = false) +{ + static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value), ""); + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs(std::move(rhs)); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs(std::move(rhs)); + assert(static_cast<bool>(lhs) == rhs_engaged); +#endif +} + +class X +{ + int i_; +public: + explicit X(int i) : i_(i) {} + X(X&& x) : i_(std::exchange(x.i_, 0)) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +class Z +{ +public: + explicit Z(int) { TEST_THROW(6); } +}; + +int main() +{ + { + optional<int> rhs; + test<X>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<X>(std::move(rhs)); + } + { + optional<int> rhs; + test<Z>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<Z>(std::move(rhs), true); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp new file mode 100644 index 0000000..9b59b02 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// template <class... Args> +// constexpr explicit optional(in_place_t, Args&&... args); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + ~X() {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(int i, int j) : i_(i), j_(j) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ +public: + Z(int i) {TEST_THROW(6);} +}; + + +int main() +{ + { + constexpr optional<int> opt(in_place, 5); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<int> + { + constexpr test_constexpr_ctor(in_place_t, int i) + : optional<int>(in_place, i) {} + }; + + } + { + const optional<X> opt(in_place); + assert(static_cast<bool>(opt) == true); + assert(*opt == X()); + } + { + const optional<X> opt(in_place, 5); + assert(static_cast<bool>(opt) == true); + assert(*opt == X(5)); + } + { + const optional<X> opt(in_place, 5, 4); + assert(static_cast<bool>(opt) == true); + assert(*opt == X(5, 4)); + } + { + constexpr optional<Y> opt(in_place); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t) + : optional<Y>(in_place) {} + }; + + } + { + constexpr optional<Y> opt(in_place, 5); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(5), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, int i) + : optional<Y>(in_place, i) {} + }; + + } + { + constexpr optional<Y> opt(in_place, 5, 4); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y(5, 4), ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, int i, int j) + : optional<Y>(in_place, i, j) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + try + { + const optional<Z> opt(in_place, 1); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp new file mode 100644 index 0000000..6d9f45a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U, class... Args> +// constexpr +// explicit optional(in_place_t, initializer_list<U> il, Args&&... args); + +#include <optional> +#include <type_traits> +#include <vector> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +class X +{ + int i_; + int j_ = 0; +public: + X() : i_(0) {} + X(int i) : i_(i) {} + X(int i, int j) : i_(i), j_(j) {} + + ~X() {} + + friend bool operator==(const X& x, const X& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Y +{ + int i_; + int j_ = 0; +public: + constexpr Y() : i_(0) {} + constexpr Y(int i) : i_(i) {} + constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {} + + friend constexpr bool operator==(const Y& x, const Y& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +class Z +{ + int i_; + int j_ = 0; +public: + Z() : i_(0) {} + Z(int i) : i_(i) {} + Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) + {TEST_THROW(6);} + + friend bool operator==(const Z& x, const Z& y) + {return x.i_ == y.i_ && x.j_ == y.j_;} +}; + +int main() +{ + { + static_assert(!std::is_constructible<X, std::initializer_list<int>&>::value, ""); + static_assert(!std::is_constructible<optional<X>, std::initializer_list<int>&>::value, ""); + } + { + optional<std::vector<int>> opt(in_place, {3, 1}); + assert(static_cast<bool>(opt) == true); + assert((*opt == std::vector<int>{3, 1})); + assert(opt->size() == 2); + } + { + optional<std::vector<int>> opt(in_place, {3, 1}, std::allocator<int>()); + assert(static_cast<bool>(opt) == true); + assert((*opt == std::vector<int>{3, 1})); + assert(opt->size() == 2); + } + { + static_assert(std::is_constructible<optional<Y>, std::initializer_list<int>&>::value, ""); + constexpr optional<Y> opt(in_place, {3, 1}); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == Y{3, 1}, ""); + + struct test_constexpr_ctor + : public optional<Y> + { + constexpr test_constexpr_ctor(in_place_t, std::initializer_list<int> i) + : optional<Y>(in_place, i) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + static_assert(std::is_constructible<optional<Z>, std::initializer_list<int>&>::value, ""); + try + { + optional<Z> opt(in_place, {3, 1}); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp new file mode 100644 index 0000000..5a4929c --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp @@ -0,0 +1,196 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// optional(optional<T>&& rhs); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +template <class T, class ...InitArgs> +void test(InitArgs&&... args) +{ + const optional<T> orig(std::forward<InitArgs>(args)...); + optional<T> rhs(orig); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(*lhs == *orig); +} + +void test_throwing_ctor() { +#ifndef TEST_HAS_NO_EXCEPTIONS + struct Z { + Z() : count(0) {} + Z(Z&& o) : count(o.count + 1) + { if (count == 2) throw 6; } + int count; + }; + Z z; + optional<Z> rhs(std::move(z)); + try + { + optional<Z> lhs(std::move(rhs)); + assert(false); + } + catch (int i) + { + assert(i == 6); + } +#endif +} + + +template <class T, class ...InitArgs> +void test_ref(InitArgs&&... args) +{ + optional<T> rhs(std::forward<InitArgs>(args)...); + bool rhs_engaged = static_cast<bool>(rhs); + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); + if (rhs_engaged) + assert(&(*lhs) == &(*rhs)); +} + +void test_reference_extension() +{ +#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. + using T = TestTypes::TestType; + T::reset(); + { + T t; + T::reset_constructors(); + test_ref<T&>(); + test_ref<T&>(t); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::destroyed == 1); + assert(T::alive == 0); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&>(); + test_ref<T const&>(t); + test_ref<T const&>(ct); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + T t; + T::reset_constructors(); + test_ref<T&&>(); + test_ref<T&&>(std::move(t)); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + T t; + const T& ct = t; + T::reset_constructors(); + test_ref<T const&&>(); + test_ref<T const&&>(std::move(t)); + test_ref<T const&&>(std::move(ct)); + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 0); + } + assert(T::alive == 0); + assert(T::destroyed == 1); + { + static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, ""); + static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, ""); + } +#endif +} + + +int main() +{ + test<int>(); + test<int>(3); + { + using T = TestTypes::TestType; + T::reset(); + optional<T> rhs; + assert(T::alive == 0); + const optional<T> lhs(std::move(rhs)); + assert(lhs.has_value() == false); + assert(rhs.has_value() == false); + assert(T::alive == 0); + } + TestTypes::TestType::reset(); + { + using T = TestTypes::TestType; + T::reset(); + optional<T> rhs(42); + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::move_constructed == 0); + const optional<T> lhs(std::move(rhs)); + assert(lhs.has_value()); + assert(rhs.has_value()); + assert(lhs.value().value == 42); + assert(rhs.value().value == -1); + assert(T::move_constructed == 1); + assert(T::alive == 2); + } + TestTypes::TestType::reset(); + { + using namespace ConstexprTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + using namespace TrivialTestTypes; + test<TestType>(); + test<TestType>(42); + } + { + test_throwing_ctor(); + } + { + struct ThrowsMove { + ThrowsMove() noexcept(false) {} + ThrowsMove(ThrowsMove const&) noexcept(false) {} + ThrowsMove(ThrowsMove &&) noexcept(false) {} + }; + static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, ""); + struct NoThrowMove { + NoThrowMove() noexcept(false) {} + NoThrowMove(NoThrowMove const&) noexcept(false) {} + NoThrowMove(NoThrowMove &&) noexcept(true) {} + }; + static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, ""); + } + { + test_reference_extension(); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp new file mode 100644 index 0000000..468a003 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr optional(nullopt_t) noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "archetypes.hpp" + +using std::optional; +using std::nullopt_t; +using std::nullopt; + +template <class Opt> +void +test_constexpr() +{ + static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, ""); + static_assert(std::is_trivially_destructible<Opt>::value, ""); + static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, ""); + + constexpr Opt opt(nullopt); + static_assert(static_cast<bool>(opt) == false, ""); + + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +template <class Opt> +void +test() +{ + static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, ""); + static_assert(!std::is_trivially_destructible<Opt>::value, ""); + static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, ""); + { + Opt opt(nullopt); + assert(static_cast<bool>(opt) == false); + } + { + const Opt opt(nullopt); + assert(static_cast<bool>(opt) == false); + } + struct test_constexpr_ctor + : public Opt + { + constexpr test_constexpr_ctor() {} + }; +} + +int main() +{ + test_constexpr<optional<int>>(); + test_constexpr<optional<int*>>(); + test_constexpr<optional<ImplicitTypes::NoCtors>>(); + test_constexpr<optional<NonTrivialTypes::NoCtors>>(); + test_constexpr<optional<NonConstexprTypes::NoCtors>>(); + test<optional<NonLiteralTypes::NoCtors>>(); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp new file mode 100644 index 0000000..0e180c1 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> +// optional(optional<U>&& rhs); + +#include <optional> +#include <type_traits> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +template <class T, class U> +void +test(optional<U>&& rhs, bool is_going_to_throw = false) +{ + bool rhs_engaged = static_cast<bool>(rhs); +#ifndef TEST_HAS_NO_EXCEPTIONS + try + { + optional<T> lhs = std::move(rhs); + assert(is_going_to_throw == false); + assert(static_cast<bool>(lhs) == rhs_engaged); + } + catch (int i) + { + assert(i == 6); + } +#else + if (is_going_to_throw) return; + optional<T> lhs = std::move(rhs); + assert(static_cast<bool>(lhs) == rhs_engaged); +#endif +} + +class X +{ + int i_; +public: + X(int i) : i_(i) {} + X(X&& x) : i_(std::exchange(x.i_, 0)) {} + ~X() {i_ = 0;} + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +int count = 0; + +struct Z +{ + Z(int) { TEST_THROW(6); } +}; + +int main() +{ + { + optional<short> rhs; + test<int>(std::move(rhs)); + } + { + optional<short> rhs(short{3}); + test<int>(std::move(rhs)); + } + { + optional<int> rhs; + test<X>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<X>(std::move(rhs)); + } + { + optional<int> rhs; + test<Z>(std::move(rhs)); + } + { + optional<int> rhs(3); + test<Z>(std::move(rhs), true); + } + + static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp new file mode 100644 index 0000000..496661d --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp @@ -0,0 +1,148 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// constexpr optional(T&& v); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + + +using std::optional; + + +class Z +{ +public: + Z(int) {} + Z(Z&&) {TEST_THROW(6);} +}; + + +int main() +{ + { + typedef int T; + constexpr optional<T> opt(T(5)); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 5, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + } + { + typedef double T; + constexpr optional<T> opt(T(3)); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(*opt == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + } + { + typedef TestTypes::TestType T; + T::reset(); + optional<T> opt = T{3}; + assert(T::alive == 1); + assert(T::move_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ExplicitTestTypes::TestType T; + static_assert(!std::is_convertible<T&&, optional<T>>::value, ""); + T::reset(); + optional<T> opt(T{3}); + assert(T::alive == 1); + assert(T::move_constructed == 1); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef TestTypes::TestType T; + T::reset(); + optional<T> opt = {3}; + assert(T::alive == 1); + assert(T::value_constructed == 1); + assert(T::copy_constructed == 0); + assert(T::move_constructed == 0); + assert(static_cast<bool>(opt) == true); + assert(opt.value().value == 3); + } + { + typedef ConstexprTestTypes::TestType T; + constexpr optional<T> opt = {T(3)}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ConstexprTestTypes::TestType T; + constexpr optional<T> opt = {3}; + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(const T&) {} + }; + } + { + typedef ExplicitConstexprTestTypes::TestType T; + static_assert(!std::is_convertible<T&&, optional<T>>::value, ""); + constexpr optional<T> opt(T{3}); + static_assert(static_cast<bool>(opt) == true, ""); + static_assert(opt.value().value == 3, ""); + + struct test_constexpr_ctor + : public optional<T> + { + constexpr test_constexpr_ctor(T&&) {} + }; + + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + struct Z { + Z(int) {} + Z(Z&&) {throw 6;} + }; + typedef Z T; + try + { + T t(3); + optional<T> opt(std::move(t)); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp new file mode 100644 index 0000000..5132c9a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// ~optional(); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct PODType { + int value; + int value2; +}; + +class X +{ +public: + static bool dtor_called; + X() = default; + ~X() {dtor_called = true;} +}; + +bool X::dtor_called = false; + +int main() +{ + { + typedef int T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef double T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef PODType T; + static_assert(std::is_trivially_destructible<T>::value, ""); + static_assert(std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(std::is_literal_type<optional<T>>::value, ""); + } + { + typedef X T; + static_assert(!std::is_trivially_destructible<T>::value, ""); + static_assert(!std::is_trivially_destructible<optional<T>>::value, ""); + static_assert(!std::is_literal_type<optional<T>>::value, ""); + { + X x; + optional<X> opt{x}; + assert(X::dtor_called == false); + } + assert(X::dtor_called == true); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp new file mode 100644 index 0000000..cee73da --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// <optional> + +// void reset() noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + static bool dtor_called; + ~X() {dtor_called = true;} +}; + +bool X::dtor_called = false; + +int main() +{ + { + optional<int> opt; + static_assert(noexcept(opt.reset()) == true, ""); + opt.reset(); + assert(static_cast<bool>(opt) == false); + } + { + optional<int> opt(3); + opt.reset(); + assert(static_cast<bool>(opt) == false); + } + { + optional<X> opt; + static_assert(noexcept(opt.reset()) == true, ""); + assert(X::dtor_called == false); + opt.reset(); + assert(X::dtor_called == false); + assert(static_cast<bool>(opt) == false); + } + assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997 + { + optional<X> opt(X{}); + X::dtor_called = false; + opt.reset(); + assert(X::dtor_called == true); + assert(static_cast<bool>(opt) == false); + X::dtor_called = false; + } + assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997 +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp new file mode 100644 index 0000000..9820d50 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr explicit optional<T>::operator bool() const noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + { + const optional<int> opt; ((void)opt); + ASSERT_NOEXCEPT(bool(opt)); + static_assert(!std::is_convertible<optional<int>, bool>::value, ""); + } + { + constexpr optional<int> opt; + static_assert(!opt, ""); + } + { + constexpr optional<int> opt(0); + static_assert(opt, ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp new file mode 100644 index 0000000..4087cfd --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T& optional<T>::operator*() &; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return (*opt).test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*opt), X&); + // ASSERT_NOT_NOEXCEPT(*opt); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert((*opt).test() == 4); + } + static_assert(test() == 7, ""); +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*opt).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp new file mode 100644 index 0000000..0779c90 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::operator*() const &; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + int test() const {return 2;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*opt), X const&); + // ASSERT_NOT_NOEXCEPT(*opt); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert((*opt).test() == 3, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert((*opt).test() == 2); + } +#ifdef _LIBCPP_DEBUG + { + const optional<X> opt; + assert((*opt).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp new file mode 100644 index 0000000..78fd992 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T&& optional<T>::operator*() const &&; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + int test() const && {return 2;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*std::move(opt)), X const &&); + // ASSERT_NOT_NOEXCEPT(*std::move(opt)); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert((*std::move(opt)).test() == 5, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert((*std::move(opt)).test() == 2); + } +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*std::move(opt)).test() == 5); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp new file mode 100644 index 0000000..2924123 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T&& optional<T>::operator*() &&; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const& {return 3;} + int test() & {return 4;} + constexpr int test() const&& {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() && {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return (*std::move(opt)).test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(*std::move(opt)), X&&); + // ASSERT_NOT_NOEXCEPT(*std::move(opt)); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator*() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert((*std::move(opt)).test() == 6); + } + static_assert(test() == 7, ""); +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert((*std::move(opt)).test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp new file mode 100644 index 0000000..5df295d --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr bool optional<T>::has_value() const noexcept; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + { + const optional<int> opt; ((void)opt); + ASSERT_NOEXCEPT(opt.has_value()); + ASSERT_SAME_TYPE(decltype(opt.has_value()), bool); + } + { + constexpr optional<int> opt; + static_assert(!opt.has_value(), ""); + } + { + constexpr optional<int> opt(0); + static_assert(opt.has_value(), ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp new file mode 100644 index 0000000..2f1648c4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T* optional<T>::operator->(); + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + int test() noexcept {return 3;} +}; + +struct Y +{ + constexpr int test() {return 3;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return opt->test(); +} + +int main() +{ + { + std::optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(opt.operator->()), X*); + // ASSERT_NOT_NOEXCEPT(opt.operator->()); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator->() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + optional<X> opt(X{}); + assert(opt->test() == 3); + } + { + static_assert(test() == 3, ""); + } +#ifdef _LIBCPP_DEBUG + { + optional<X> opt; + assert(opt->test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp new file mode 100644 index 0000000..887edc7 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T* optional<T>::operator->() const; + +#ifdef _LIBCPP_DEBUG +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; + +struct X +{ + constexpr int test() const {return 3;} +}; + +struct Y +{ + int test() const noexcept {return 2;} +}; + +struct Z +{ + const Z* operator&() const; + constexpr int test() const {return 1;} +}; + +int main() +{ + { + const std::optional<X> opt; ((void)opt); + ASSERT_SAME_TYPE(decltype(opt.operator->()), X const*); + // ASSERT_NOT_NOEXCEPT(opt.operator->()); + // FIXME: This assertion fails with GCC because it can see that + // (A) operator->() is constexpr, and + // (B) there is no path through the function that throws. + // It's arguable if this is the correct behavior for the noexcept + // operator. + // Regardless this function should still be noexcept(false) because + // it has a narrow contract. + } + { + constexpr optional<X> opt(X{}); + static_assert(opt->test() == 3, ""); + } + { + constexpr optional<Y> opt(Y{}); + assert(opt->test() == 2); + } + { + constexpr optional<Z> opt(Z{}); + static_assert(opt->test() == 1, ""); + } +#ifdef _LIBCPP_DEBUG + { + const optional<X> opt; + assert(opt->test() == 3); + assert(false); + } +#endif // _LIBCPP_DEBUG +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp new file mode 100644 index 0000000..516a79d --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T& optional<T>::value() &; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() & {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return opt.value().test(); +} + + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(opt.value()); + ASSERT_SAME_TYPE(decltype(opt.value()), X&); + } + { + optional<X> opt; + opt.emplace(); + assert(opt.value().test() == 4); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + try + { + opt.value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif + static_assert(test() == 7, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp new file mode 100644 index 0000000..6076c50 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::value() const &; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + constexpr int test() const {return 3;} + int test() {return 4;} +}; + +int main() +{ + { + constexpr optional<X> opt; + static_assert(opt.value().test() == 3, ""); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp new file mode 100644 index 0000000..d4038e4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::value() const &; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(opt.value()); + ASSERT_SAME_TYPE(decltype(opt.value()), X const&); + } + { + constexpr optional<X> opt(in_place); + static_assert(opt.value().test() == 3, ""); + } + { + const optional<X> opt(in_place); + assert(opt.value().test() == 3); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + const optional<X> opt; + try + { + opt.value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp new file mode 100644 index 0000000..e189d3a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr const T& optional<T>::value() const &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +int main() +{ + { + const optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(std::move(opt).value()); + ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X const&&); + } + { + constexpr optional<X> opt(in_place); + static_assert(std::move(opt).value().test() == 5, ""); + } + { + const optional<X> opt(in_place); + assert(std::move(opt).value().test() == 5); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + const optional<X> opt; + try + { + std::move(opt).value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp new file mode 100644 index 0000000..c219e97 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> T optional<T>::value_or(U&& v) &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::in_place_t; +using std::in_place; + +struct Y +{ + int i_; + + Y(int i) : i_(i) {} +}; + +struct X +{ + int i_; + + X(int i) : i_(i) {} + X(X&& x) : i_(x.i_) {x.i_ = 0;} + X(const Y& y) : i_(y.i_) {} + X(Y&& y) : i_(y.i_+1) {} + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_;} +}; + +int main() +{ + { + optional<X> opt(in_place, 2); + Y y(3); + assert(std::move(opt).value_or(y) == 2); + assert(*opt == 0); + } + { + optional<X> opt(in_place, 2); + assert(std::move(opt).value_or(Y(3)) == 2); + assert(*opt == 0); + } + { + optional<X> opt; + Y y(3); + assert(std::move(opt).value_or(y) == 3); + assert(!opt); + } + { + optional<X> opt; + assert(std::move(opt).value_or(Y(3)) == 4); + assert(!opt); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp new file mode 100644 index 0000000..36a8581 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class U> constexpr T optional<T>::value_or(U&& v) const&; + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct Y +{ + int i_; + + constexpr Y(int i) : i_(i) {} +}; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} + constexpr X(const Y& y) : i_(y.i_) {} + constexpr X(Y&& y) : i_(y.i_+1) {} + friend constexpr bool operator==(const X& x, const X& y) + {return x.i_ == y.i_;} +}; + +int main() +{ + { + constexpr optional<X> opt(2); + constexpr Y y(3); + static_assert(opt.value_or(y) == 2, ""); + } + { + constexpr optional<X> opt(2); + static_assert(opt.value_or(Y(3)) == 2, ""); + } + { + constexpr optional<X> opt; + constexpr Y y(3); + static_assert(opt.value_or(y) == 3, ""); + } + { + constexpr optional<X> opt; + static_assert(opt.value_or(Y(3)) == 4, ""); + } + { + const optional<X> opt(2); + const Y y(3); + assert(opt.value_or(y) == 2); + } + { + const optional<X> opt(2); + assert(opt.value_or(Y(3)) == 2); + } + { + const optional<X> opt; + const Y y(3); + assert(opt.value_or(y) == 3); + } + { + const optional<X> opt; + assert(opt.value_or(Y(3)) == 4); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp new file mode 100644 index 0000000..2ef485b --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// constexpr T& optional<T>::value() &&; + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +using std::optional; +using std::bad_optional_access; + +struct X +{ + X() = default; + X(const X&) = delete; + constexpr int test() const & {return 3;} + int test() & {return 4;} + constexpr int test() const && {return 5;} + int test() && {return 6;} +}; + +struct Y +{ + constexpr int test() && {return 7;} +}; + +constexpr int +test() +{ + optional<Y> opt{Y{}}; + return std::move(opt).value().test(); +} + +int main() +{ + { + optional<X> opt; ((void)opt); + ASSERT_NOT_NOEXCEPT(std::move(opt).value()); + ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X&&); + } + { + optional<X> opt; + opt.emplace(); + assert(std::move(opt).value().test() == 6); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<X> opt; + try + { + std::move(opt).value(); + assert(false); + } + catch (const bad_optional_access&) + { + } + } +#endif + static_assert(test() == 7, ""); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp new file mode 100644 index 0000000..bd9c393 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp @@ -0,0 +1,306 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// void swap(optional&) +// noexcept(is_nothrow_move_constructible<T>::value && +// is_nothrow_swappable<T>::value) + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; +public: + static unsigned dtor_called; + X(int i) : i_(i) {} + X(X&& x) = default; + X& operator=(X&&) = default; + ~X() {++dtor_called;} + + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +unsigned X::dtor_called = 0; + +class Y +{ + int i_; +public: + static unsigned dtor_called; + Y(int i) : i_(i) {} + Y(Y&&) = default; + ~Y() {++dtor_called;} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} + friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);} +}; + +unsigned Y::dtor_called = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {} + Z(Z&&) {TEST_THROW(7);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} + friend void swap(Z& x, Z& y) {TEST_THROW(6);} +}; + + +int main() +{ + { + optional<int> opt1; + optional<int> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<int> opt1; + optional<int> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(X::dtor_called == 0); + } + { + optional<X> opt1(1); + optional<X> opt2; + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<X> opt1(1); + optional<X> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + opt1.swap(opt2); + assert(X::dtor_called == 1); // from inside std::swap + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(Y::dtor_called == 0); + } + { + optional<Y> opt1(1); + optional<Y> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Y> opt1(1); + optional<Y> opt2(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + opt1.swap(opt2); + assert(Y::dtor_called == 0); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Z> opt1; + optional<Z> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + opt1.swap(opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Z> opt1; + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(opt1.swap(opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + opt1.swap(opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } +#endif +} diff --git a/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp new file mode 100644 index 0000000..8a2c77a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// T shall be an object type and shall satisfy the requirements of Destructible + +#include <optional> + +using std::optional; + +struct X +{ +private: + ~X() {} +}; + +int main() +{ + using std::optional; + { + // expected-error@optional:* 2 {{static_assert failed "instantiation of optional with a reference type is ill-formed}} + optional<int&> opt1; + optional<int&&> opt2; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed"}} + optional<X> opt3; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}} + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}} + optional<void()> opt4; + } + { + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}} + // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}} + // expected-error@optional:* 1+ {{cannot form a reference to 'void'}} + optional<const void> opt4; + } + // FIXME these are garbage diagnostics that Clang should not produce + // expected-error@optional:* 0+ {{is not a base class}} +} diff --git a/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp new file mode 100644 index 0000000..fdd0f15 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "archetypes.hpp" + +template <class T> +struct SpecialMemberTest { + using O = std::optional<T>; + + static_assert(std::is_default_constructible_v<O>, + "optional is always default constructible."); + static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>, + "optional<T> is copy constructible if and only if T is copy constructible."); + static_assert(std::is_move_constructible_v<O> == + (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>), + "optional<T> is move constructible if and only if T is copy or move constructible."); + static_assert(std::is_copy_assignable_v<O> == + (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>), + "optional<T> is copy assignable if and only if T is both copy " + "constructible and copy assignable."); + static_assert(std::is_move_assignable_v<O> == + ((std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>) || + (std::is_move_constructible_v<T> && std::is_move_assignable_v<T>)), + "optional<T> is move assignable if and only if T is both move assignable and " + "move constructible, or both copy constructible and copy assignable."); +}; + +template <class ...Args> static void sink(Args&&...) {} + +template <class ...TestTypes> +struct DoTestsMetafunction { + DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); } +}; + +struct TrivialMoveNonTrivialCopy { + TrivialMoveNonTrivialCopy() = default; + TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {} + TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default; + TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; } + TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default; +}; + +struct TrivialCopyNonTrivialMove { + TrivialCopyNonTrivialMove() = default; + TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {} + TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default; + TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; } +}; + +int main() +{ + sink( + ImplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + ExplicitTypes::ApplyTypes<DoTestsMetafunction>{}, + NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{}, + NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{}, + DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{} + ); +} diff --git a/libcxx/test/std/utilities/optional/optional.object/types.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/types.pass.cpp new file mode 100644 index 0000000..0230a13 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/types.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> +// class optional +// { +// public: +// typedef T value_type; +// ... + +#include <optional> +#include <type_traits> + +using std::optional; + +template <class Opt, class T> +void +test() +{ + static_assert(std::is_same<typename Opt::value_type, T>::value, ""); +} + +int main() +{ + test<optional<int>, int>(); + test<optional<const int>, const int>(); + test<optional<double>, double>(); + test<optional<const double>, const double>(); +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp new file mode 100644 index 0000000..6650b67 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator == ( const X &lhs, const X &rhs ) + { return lhs.i_ == rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( o1 == o1 , "" ); + static_assert ( o1 == o2 , "" ); + static_assert ( !(o1 == o3), "" ); + static_assert ( !(o1 == o4), "" ); + static_assert ( !(o1 == o5), "" ); + + static_assert ( o2 == o1 , "" ); + static_assert ( o2 == o2 , "" ); + static_assert ( !(o2 == o3), "" ); + static_assert ( !(o2 == o4), "" ); + static_assert ( !(o2 == o5), "" ); + + static_assert ( !(o3 == o1), "" ); + static_assert ( !(o3 == o2), "" ); + static_assert ( o3 == o3 , "" ); + static_assert ( !(o3 == o4), "" ); + static_assert ( o3 == o5 , "" ); + + static_assert ( !(o4 == o1), "" ); + static_assert ( !(o4 == o2), "" ); + static_assert ( !(o4 == o3), "" ); + static_assert ( o4 == o4 , "" ); + static_assert ( !(o4 == o5), "" ); + + static_assert ( !(o5 == o1), "" ); + static_assert ( !(o5 == o2), "" ); + static_assert ( o5 == o3 , "" ); + static_assert ( !(o5 == o4), "" ); + static_assert ( o5 == o5 , "" ); + + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp new file mode 100644 index 0000000..f9b3044 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator>= (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator >= ( const X &lhs, const X &rhs ) + { return lhs.i_ >= rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( (o1 >= o1), "" ); + static_assert ( (o1 >= o2), "" ); + static_assert ( !(o1 >= o3), "" ); + static_assert ( !(o1 >= o4), "" ); + static_assert ( !(o1 >= o5), "" ); + + static_assert ( (o2 >= o1), "" ); + static_assert ( (o2 >= o2), "" ); + static_assert ( !(o2 >= o3), "" ); + static_assert ( !(o2 >= o4), "" ); + static_assert ( !(o2 >= o5), "" ); + + static_assert ( (o3 >= o1), "" ); + static_assert ( (o3 >= o2), "" ); + static_assert ( (o3 >= o3), "" ); + static_assert ( !(o3 >= o4), "" ); + static_assert ( (o3 >= o5), "" ); + + static_assert ( (o4 >= o1), "" ); + static_assert ( (o4 >= o2), "" ); + static_assert ( (o4 >= o3), "" ); + static_assert ( (o4 >= o4), "" ); + static_assert ( (o4 >= o5), "" ); + + static_assert ( (o5 >= o1), "" ); + static_assert ( (o5 >= o2), "" ); + static_assert ( (o5 >= o3), "" ); + static_assert ( !(o5 >= o4), "" ); + static_assert ( (o5 >= o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp new file mode 100644 index 0000000..8a27eb4 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator> (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator > ( const X &lhs, const X &rhs ) + { return lhs.i_ > rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 > o1), "" ); + static_assert ( !(o1 > o2), "" ); + static_assert ( !(o1 > o3), "" ); + static_assert ( !(o1 > o4), "" ); + static_assert ( !(o1 > o5), "" ); + + static_assert ( !(o2 > o1), "" ); + static_assert ( !(o2 > o2), "" ); + static_assert ( !(o2 > o3), "" ); + static_assert ( !(o2 > o4), "" ); + static_assert ( !(o2 > o5), "" ); + + static_assert ( (o3 > o1), "" ); + static_assert ( (o3 > o2), "" ); + static_assert ( !(o3 > o3), "" ); + static_assert ( !(o3 > o4), "" ); + static_assert ( !(o3 > o5), "" ); + + static_assert ( (o4 > o1), "" ); + static_assert ( (o4 > o2), "" ); + static_assert ( (o4 > o3), "" ); + static_assert ( !(o4 > o4), "" ); + static_assert ( (o4 > o5), "" ); + + static_assert ( (o5 > o1), "" ); + static_assert ( (o5 > o2), "" ); + static_assert ( !(o5 > o3), "" ); + static_assert ( !(o5 > o4), "" ); + static_assert ( !(o5 > o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp new file mode 100644 index 0000000..a7d594d --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator<= (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator <= ( const X &lhs, const X &rhs ) + { return lhs.i_ <= rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( (o1 <= o1), "" ); + static_assert ( (o1 <= o2), "" ); + static_assert ( (o1 <= o3), "" ); + static_assert ( (o1 <= o4), "" ); + static_assert ( (o1 <= o5), "" ); + + static_assert ( (o2 <= o1), "" ); + static_assert ( (o2 <= o2), "" ); + static_assert ( (o2 <= o3), "" ); + static_assert ( (o2 <= o4), "" ); + static_assert ( (o2 <= o5), "" ); + + static_assert ( !(o3 <= o1), "" ); + static_assert ( !(o3 <= o2), "" ); + static_assert ( (o3 <= o3), "" ); + static_assert ( (o3 <= o4), "" ); + static_assert ( (o3 <= o5), "" ); + + static_assert ( !(o4 <= o1), "" ); + static_assert ( !(o4 <= o2), "" ); + static_assert ( !(o4 <= o3), "" ); + static_assert ( (o4 <= o4), "" ); + static_assert ( !(o4 <= o5), "" ); + + static_assert ( !(o5 <= o1), "" ); + static_assert ( !(o5 <= o2), "" ); + static_assert ( (o5 <= o3), "" ); + static_assert ( (o5 <= o4), "" ); + static_assert ( (o5 <= o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp new file mode 100644 index 0000000..deffa5e --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator< (const optional<T>& x, const optional<T>& y); + +#include <optional> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator < ( const X &lhs, const X &rhs ) + { return lhs.i_ < rhs.i_ ; } + +int main() +{ + { + typedef optional<X> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 < o1), "" ); + static_assert ( !(o1 < o2), "" ); + static_assert ( (o1 < o3), "" ); + static_assert ( (o1 < o4), "" ); + static_assert ( (o1 < o5), "" ); + + static_assert ( !(o2 < o1), "" ); + static_assert ( !(o2 < o2), "" ); + static_assert ( (o2 < o3), "" ); + static_assert ( (o2 < o4), "" ); + static_assert ( (o2 < o5), "" ); + + static_assert ( !(o3 < o1), "" ); + static_assert ( !(o3 < o2), "" ); + static_assert ( !(o3 < o3), "" ); + static_assert ( (o3 < o4), "" ); + static_assert ( !(o3 < o5), "" ); + + static_assert ( !(o4 < o1), "" ); + static_assert ( !(o4 < o2), "" ); + static_assert ( !(o4 < o3), "" ); + static_assert ( !(o4 < o4), "" ); + static_assert ( !(o4 < o5), "" ); + + static_assert ( !(o5 < o1), "" ); + static_assert ( !(o5 < o2), "" ); + static_assert ( !(o5 < o3), "" ); + static_assert ( (o5 < o4), "" ); + static_assert ( !(o5 < o5), "" ); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp new file mode 100644 index 0000000..fd11b2a --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y); + +#include <optional> +#include <type_traits> +#include <cassert> + +using std::optional; + +struct X +{ + int i_; + + constexpr X(int i) : i_(i) {} +}; + +constexpr bool operator != ( const X &lhs, const X &rhs ) + { return lhs.i_ != rhs.i_ ; } + +int main() +{ + { + typedef X T; + typedef optional<T> O; + + constexpr O o1; // disengaged + constexpr O o2; // disengaged + constexpr O o3{1}; // engaged + constexpr O o4{2}; // engaged + constexpr O o5{1}; // engaged + + static_assert ( !(o1 != o1), "" ); + static_assert ( !(o1 != o2), "" ); + static_assert ( (o1 != o3), "" ); + static_assert ( (o1 != o4), "" ); + static_assert ( (o1 != o5), "" ); + + static_assert ( !(o2 != o1), "" ); + static_assert ( !(o2 != o2), "" ); + static_assert ( (o2 != o3), "" ); + static_assert ( (o2 != o4), "" ); + static_assert ( (o2 != o5), "" ); + + static_assert ( (o3 != o1), "" ); + static_assert ( (o3 != o2), "" ); + static_assert ( !(o3 != o3), "" ); + static_assert ( (o3 != o4), "" ); + static_assert ( !(o3 != o5), "" ); + + static_assert ( (o4 != o1), "" ); + static_assert ( (o4 != o2), "" ); + static_assert ( (o4 != o3), "" ); + static_assert ( !(o4 != o4), "" ); + static_assert ( (o4 != o5), "" ); + + static_assert ( (o5 != o1), "" ); + static_assert ( (o5 != o2), "" ); + static_assert ( !(o5 != o3), "" ); + static_assert ( (o5 != o4), "" ); + static_assert ( !(o5 != o5), "" ); + + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp new file mode 100644 index 0000000..3fbf19f --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> +// constexpr optional<decay_t<T>> make_optional(T&& v); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +int main() +{ + using std::optional; + using std::make_optional; + { + int arr[10]; ((void)arr); + ASSERT_SAME_TYPE(decltype(make_optional(arr)), optional<int*>); + } + { + constexpr auto opt = make_optional(2); + ASSERT_SAME_TYPE(decltype(opt), const optional<int>); + static_assert(opt.value() == 2); + } + { + optional<int> opt = make_optional(2); + assert(*opt == 2); + } + { + std::string s("123"); + optional<std::string> opt = make_optional(s); + assert(*opt == s); + } + { + std::unique_ptr<int> s(new int(3)); + optional<std::unique_ptr<int>> opt = make_optional(std::move(s)); + assert(**opt == 3); + assert(s == nullptr); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp new file mode 100644 index 0000000..bdfeefb --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T, class... Args> +// constexpr optional<T> make_optional(Args&&... args); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +int main() +{ + using std::optional; + using std::make_optional; + + { + constexpr auto opt = make_optional<int>('a'); + static_assert(*opt == int('a'), ""); + } + { + std::string s("123"); + auto opt = make_optional<std::string>(s); + assert(*opt == s); + } + { + std::unique_ptr<int> s(new int(3)); + auto opt = make_optional<std::unique_ptr<int>>(std::move(s)); + assert(**opt == 3); + assert(s == nullptr); + } + { + auto opt = make_optional<std::string>(4, 'X'); + assert(*opt == "XXXX"); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp new file mode 100644 index 0000000..f17f582 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T, class U, class... Args> +// constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); + +#include <optional> +#include <string> +#include <memory> +#include <cassert> + +#include "test_macros.h" + +struct TestT { + int x; + int size; + constexpr TestT(std::initializer_list<int> il) : x(*il.begin()), size(il.size()) {} + constexpr TestT(std::initializer_list<int> il, const int*) + : x(*il.begin()), size(il.size()) {} +}; + +int main() +{ + using std::make_optional; + { + constexpr auto opt = make_optional<TestT>({42, 2, 3}); + ASSERT_SAME_TYPE(decltype(opt), const std::optional<TestT>); + static_assert(opt->x == 42, ""); + static_assert(opt->size == 3, ""); + } + { + constexpr auto opt = make_optional<TestT>({42, 2, 3}, nullptr); + static_assert(opt->x == 42, ""); + static_assert(opt->size == 3, ""); + } + { + auto opt = make_optional<std::string>({'1', '2', '3'}); + assert(*opt == "123"); + } + { + auto opt = make_optional<std::string>({'a', 'b', 'c'}, std::allocator<char>{}); + assert(*opt == "abc"); + } +} diff --git a/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp new file mode 100644 index 0000000..9f1d0305 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp @@ -0,0 +1,352 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// template <class T> void swap(optional<T>& x, optional<T>& y) +// noexcept(noexcept(x.swap(y))); + +#include <optional> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +class X +{ + int i_; +public: + static unsigned dtor_called; + X(int i) : i_(i) {} + X(X&& x) = default; + X& operator=(X&&) = default; + ~X() {++dtor_called;} + + friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} +}; + +unsigned X::dtor_called = 0; + +class Y +{ + int i_; +public: + static unsigned dtor_called; + Y(int i) : i_(i) {} + Y(Y&&) = default; + ~Y() {++dtor_called;} + + friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} + friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);} +}; + +unsigned Y::dtor_called = 0; + +class Z +{ + int i_; +public: + Z(int i) : i_(i) {} + Z(Z&&) { TEST_THROW(7);} + + friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} + friend void swap(Z& x, Z& y) { TEST_THROW(6);} +}; + + +struct NonSwappable { + NonSwappable(NonSwappable const&) = delete; +}; +void swap(NonSwappable&, NonSwappable&) = delete; + +void test_swap_sfinae() { + using std::optional; + { + using T = TestTypes::TestType; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::MoveOnly; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::Copyable; + static_assert(std::is_swappable_v<optional<T>>, ""); + } + { + using T = TestTypes::NoCtors; + static_assert(!std::is_swappable_v<optional<T>>, ""); + } + { + using T = NonSwappable; + static_assert(!std::is_swappable_v<optional<T>>, ""); + } + { + // Even thought CopyOnly has deleted move operations, those operations + // cause optional<CopyOnly> to have implicitly deleted move operations + // that decay into copies. + using T = TestTypes::CopyOnly; + using Opt = optional<T>; + T::reset(); + Opt L(101), R(42); + T::reset_constructors(); + std::swap(L, R); + assert(L->value == 42); + assert(R->value == 101); + assert(T::copy_constructed == 1); + assert(T::constructed == T::copy_constructed); + assert(T::assigned == 2); + assert(T::assigned == T::copy_assigned); + } +} + +int main() +{ + test_swap_sfinae(); + { + optional<int> opt1; + optional<int> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<int> opt1; + optional<int> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<int> opt1(1); + optional<int> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(X::dtor_called == 0); + } + { + optional<X> opt1(1); + optional<X> opt2; + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<X> opt1; + optional<X> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<X> opt1(1); + optional<X> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == true, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + X::dtor_called = 0; + swap(opt1, opt2); + assert(X::dtor_called == 1); // from inside std::swap + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + assert(Y::dtor_called == 0); + } + { + optional<Y> opt1(1); + optional<Y> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Y> opt1; + optional<Y> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 1); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Y> opt1(1); + optional<Y> opt2(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + Y::dtor_called = 0; + swap(opt1, opt2); + assert(Y::dtor_called == 0); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 2); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 1); + } + { + optional<Z> opt1; + optional<Z> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + swap(opt1, opt2); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == false); + } +#ifndef TEST_HAS_NO_EXCEPTIONS + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == false); + } + { + optional<Z> opt1; + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 7); + } + assert(static_cast<bool>(opt1) == false); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } + { + optional<Z> opt1; + opt1.emplace(1); + optional<Z> opt2; + opt2.emplace(2); + static_assert(noexcept(swap(opt1, opt2)) == false, ""); + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + try + { + swap(opt1, opt2); + assert(false); + } + catch (int i) + { + assert(i == 6); + } + assert(static_cast<bool>(opt1) == true); + assert(*opt1 == 1); + assert(static_cast<bool>(opt2) == true); + assert(*opt2 == 2); + } +#endif // TEST_HAS_NO_EXCEPTIONS +} diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp new file mode 100644 index 0000000..20c90c7 --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// A program that necessitates the instantiation of template optional for +// (possibly cv-qualified) in_place_t is ill-formed. + +#include <optional> + +int main() +{ + using std::optional; + using std::in_place_t; + using std::in_place; + + optional<in_place_t> opt; // expected-note {{requested here}} + // expected-error@optional:* {{"instantiation of optional with in_place_t is ill-formed"}} +} diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp new file mode 100644 index 0000000..687625e --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// #include <initializer_list> + +#include <optional> + +int main() +{ + using std::optional; + + std::initializer_list<int> list; +} diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp new file mode 100644 index 0000000..56a30cc --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// <optional> + +// A program that necessitates the instantiation of template optional for +// (possibly cv-qualified) nullopt_t is ill-formed. + +#include <optional> + +int main() +{ + using std::optional; + using std::nullopt_t; + using std::nullopt; + + optional<nullopt_t> opt; // expected-note 1 {{requested here}} + optional<const nullopt_t> opt1; // expected-note 1 {{requested here}} + optional<nullopt_t &> opt2; // expected-note 1 {{requested here}} + optional<nullopt_t &&> opt3; // expected-note 1 {{requested here}} + // expected-error@optional:* 4 {{instantiation of optional with nullopt_t is ill-formed}} +} diff --git a/libcxx/test/support/archetypes.hpp b/libcxx/test/support/archetypes.hpp index 5b29404..c09aa70 100644 --- a/libcxx/test/support/archetypes.hpp +++ b/libcxx/test/support/archetypes.hpp @@ -1,10 +1,186 @@ #ifndef TEST_SUPPORT_ARCHETYPES_HPP #define TEST_SUPPORT_ARCHETYPES_HPP +#include <type_traits> +#include <cassert> + #include "test_macros.h" #if TEST_STD_VER >= 11 +namespace ArchetypeBases { + +template <bool, class T> +struct DepType : T {}; + +struct NullBase {}; + +template <class Derived, bool Explicit = false> +struct TestBase { + static int alive; + static int constructed; + static int value_constructed; + static int default_constructed; + static int copy_constructed; + static int move_constructed; + static int assigned; + static int value_assigned; + static int copy_assigned; + static int move_assigned; + static int destroyed; + + static void reset() { + assert(alive == 0); + alive = 0; + reset_constructors(); + } + + static void reset_constructors() { + constructed = value_constructed = default_constructed = + copy_constructed = move_constructed = 0; + assigned = value_assigned = copy_assigned = move_assigned = destroyed = 0; + } + + TestBase() noexcept : value(0) { + ++alive; ++constructed; ++default_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit TestBase(int x) noexcept : value(x) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + TestBase(int x) noexcept : value(x) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit TestBase(int x, int y) noexcept : value(y) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + TestBase(int x, int y) noexcept : value(y) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit TestBase(std::initializer_list<int>& il, int y = 0) noexcept + : value(il.size()) { + ++alive; ++constructed; ++value_constructed; + } + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + TestBase(std::initializer_list<int>& il, int y = 0) noexcept : value(il.size()) { + ++alive; ++constructed; ++value_constructed; + } + TestBase& operator=(int xvalue) noexcept { + value = xvalue; + ++assigned; ++value_assigned; + return *this; + } +protected: + ~TestBase() { + assert(value != -999); assert(alive > 0); + --alive; ++destroyed; value = -999; + } + TestBase(TestBase const& o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + ++alive; ++constructed; ++copy_constructed; + } + TestBase(TestBase && o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + ++alive; ++constructed; ++move_constructed; + o.value = -1; + } + TestBase& operator=(TestBase const& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + ++assigned; ++copy_assigned; + value = o.value; + return *this; + } + TestBase& operator=(TestBase&& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + ++assigned; ++move_assigned; + value = o.value; + o.value = -1; + return *this; + } +public: + int value; +}; + +template <class D, bool E> int TestBase<D, E>::alive = 0; +template <class D, bool E> int TestBase<D, E>::constructed = 0; +template <class D, bool E> int TestBase<D, E>::value_constructed = 0; +template <class D, bool E> int TestBase<D, E>::default_constructed = 0; +template <class D, bool E> int TestBase<D, E>::copy_constructed = 0; +template <class D, bool E> int TestBase<D, E>::move_constructed = 0; +template <class D, bool E> int TestBase<D, E>::assigned = 0; +template <class D, bool E> int TestBase<D, E>::value_assigned = 0; +template <class D, bool E> int TestBase<D, E>::copy_assigned = 0; +template <class D, bool E> int TestBase<D, E>::move_assigned = 0; +template <class D, bool E> int TestBase<D, E>::destroyed = 0; + +template <bool Explicit = false> +struct ValueBase { + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr ValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr ValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr ValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr ValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr ValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr ValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {} + constexpr ValueBase& operator=(int xvalue) noexcept { + value = xvalue; + return *this; + } + //~ValueBase() { assert(value != -999); value = -999; } + int value; +protected: + constexpr ValueBase() noexcept : value(0) {} + constexpr ValueBase(ValueBase const& o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + } + constexpr ValueBase(ValueBase && o) noexcept : value(o.value) { + assert(o.value != -1); assert(o.value != -999); + o.value = -1; + } + constexpr ValueBase& operator=(ValueBase const& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + value = o.value; + return *this; + } + constexpr ValueBase& operator=(ValueBase&& o) noexcept { + assert(o.value != -1); assert(o.value != -999); + value = o.value; + o.value = -1; + return *this; + } +}; + + +template <bool Explicit = false> +struct TrivialValueBase { + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr TrivialValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr TrivialValueBase(int x) : value(x) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr TrivialValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr TrivialValueBase(int x, int y) : value(y) {} + template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true> + explicit constexpr TrivialValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {} + template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true> + constexpr TrivialValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {}; + int value; +protected: + constexpr TrivialValueBase() noexcept : value(0) {} +}; + +} + //============================================================================// // Trivial Implicit Test Types namespace ImplicitTypes { @@ -18,9 +194,18 @@ namespace ExplicitTypes { #include "archetypes.ipp" } + +//============================================================================// +// +namespace NonConstexprTypes { +#define DEFINE_CONSTEXPR +#include "archetypes.ipp" +} + //============================================================================// -// Non-Trivial Implicit Test Types +// Non-literal implicit test types namespace NonLiteralTypes { +#define DEFINE_ASSIGN_CONSTEXPR #define DEFINE_DTOR(Name) ~Name() {} #include "archetypes.ipp" } @@ -29,9 +214,144 @@ namespace NonLiteralTypes { // Non-Trivially Copyable Implicit Test Types namespace NonTrivialTypes { #define DEFINE_CTOR {} +#define DEFINE_ASSIGN { return *this; } +#define DEFINE_DEFAULT_CTOR = default +#include "archetypes.ipp" +} + +//============================================================================// +// Implicit counting types +namespace TestTypes { +#define DEFINE_CONSTEXPR +#define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} + +//============================================================================// +// Implicit counting types +namespace ExplicitTestTypes { +#define DEFINE_CONSTEXPR +#define DEFINE_EXPLICIT explicit +#define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name, true> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} + +//============================================================================// +// Implicit value types +namespace ConstexprTestTypes { +#define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace ValueTypes + + +//============================================================================// +// +namespace ExplicitConstexprTestTypes { +#define DEFINE_EXPLICIT explicit +#define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<true> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace ValueTypes + + +//============================================================================// +// +namespace TrivialTestTypes { +#define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<false> +#include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; +} + +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace TrivialValueTypes + +//============================================================================// +// +namespace ExplicitTrivialTestTypes { +#define DEFINE_EXPLICIT explicit +#define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<true> #include "archetypes.ipp" + +using TestType = AllCtors; + +// Add equality operators +template <class Tp> +constexpr bool operator==(Tp const& L, Tp const& R) noexcept { + return L.value == R.value; } +template <class Tp> +constexpr bool operator!=(Tp const& L, Tp const& R) noexcept { + return L.value != R.value; +} + +} // end namespace ExplicitTrivialTestTypes + #endif // TEST_STD_VER >= 11 #endif // TEST_SUPPORT_ARCHETYPES_HPP diff --git a/libcxx/test/support/archetypes.ipp b/libcxx/test/support/archetypes.ipp index 094440a..1f94ddc 100644 --- a/libcxx/test/support/archetypes.ipp +++ b/libcxx/test/support/archetypes.ipp @@ -1,10 +1,22 @@ +#ifndef DEFINE_BASE +#define DEFINE_BASE(Name) ::ArchetypeBases::NullBase +#endif #ifndef DEFINE_EXPLICIT #define DEFINE_EXPLICIT #endif +#ifndef DEFINE_CONSTEXPR +#define DEFINE_CONSTEXPR constexpr +#endif +#ifndef DEFINE_ASSIGN_CONSTEXPR +#define DEFINE_ASSIGN_CONSTEXPR DEFINE_CONSTEXPR +#endif #ifndef DEFINE_CTOR #define DEFINE_CTOR = default #endif +#ifndef DEFINE_DEFAULT_CTOR +#define DEFINE_DEFAULT_CTOR DEFINE_CTOR +#endif #ifndef DEFINE_ASSIGN #define DEFINE_ASSIGN = default #endif @@ -12,78 +24,117 @@ #define DEFINE_DTOR(Name) #endif -struct NoDefault { - DEFINE_EXPLICIT NoDefault() = delete; +struct AllCtors : DEFINE_BASE(AllCtors) { + using Base = DEFINE_BASE(AllCtors); + using Base::Base; + using Base::operator=; + DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors(AllCtors const&) DEFINE_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors(AllCtors &&) DEFINE_CTOR; + DEFINE_ASSIGN_CONSTEXPR AllCtors& operator=(AllCtors const&) DEFINE_ASSIGN; + DEFINE_ASSIGN_CONSTEXPR AllCtors& operator=(AllCtors &&) DEFINE_ASSIGN; + DEFINE_DTOR(AllCtors) +}; + +struct NoCtors : DEFINE_BASE(NoCtors) { + using Base = DEFINE_BASE(NoCtors); + using Base::Base; + DEFINE_EXPLICIT NoCtors() = delete; + DEFINE_EXPLICIT NoCtors(NoCtors const&) = delete; + NoCtors& operator=(NoCtors const&) = delete; + DEFINE_DTOR(NoCtors) +}; + +struct NoDefault : DEFINE_BASE(NoDefault) { + using Base = DEFINE_BASE(NoDefault); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR NoDefault() = delete; DEFINE_DTOR(NoDefault) }; -struct AllCtors { - DEFINE_EXPLICIT AllCtors() DEFINE_CTOR; - DEFINE_EXPLICIT AllCtors(AllCtors const&) DEFINE_CTOR; - DEFINE_EXPLICIT AllCtors(AllCtors &&) DEFINE_CTOR; - AllCtors& operator=(AllCtors const&) DEFINE_ASSIGN; - AllCtors& operator=(AllCtors &&) DEFINE_ASSIGN; - DEFINE_DTOR(AllCtors) +struct DefaultOnly : DEFINE_BASE(DefaultOnly) { + using Base = DEFINE_BASE(DefaultOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR DefaultOnly() DEFINE_DEFAULT_CTOR; + DefaultOnly(DefaultOnly const&) = delete; + DefaultOnly& operator=(DefaultOnly const&) = delete; + DEFINE_DTOR(DefaultOnly) }; -struct Copyable { - DEFINE_EXPLICIT Copyable() DEFINE_CTOR; - DEFINE_EXPLICIT Copyable(Copyable const &) DEFINE_CTOR; +struct Copyable : DEFINE_BASE(Copyable) { + using Base = DEFINE_BASE(Copyable); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR Copyable() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR Copyable(Copyable const &) DEFINE_CTOR; Copyable &operator=(Copyable const &) DEFINE_ASSIGN; DEFINE_DTOR(Copyable) }; -struct CopyOnly { - DEFINE_EXPLICIT CopyOnly() DEFINE_CTOR; - DEFINE_EXPLICIT CopyOnly(CopyOnly const &) DEFINE_CTOR; - DEFINE_EXPLICIT CopyOnly(CopyOnly &&) = delete; +struct CopyOnly : DEFINE_BASE(CopyOnly) { + using Base = DEFINE_BASE(CopyOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly(CopyOnly const &) DEFINE_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly(CopyOnly &&) = delete; CopyOnly &operator=(CopyOnly const &) DEFINE_ASSIGN; CopyOnly &operator=(CopyOnly &&) = delete; DEFINE_DTOR(CopyOnly) }; -struct NonCopyable { - DEFINE_EXPLICIT NonCopyable() DEFINE_CTOR; - DEFINE_EXPLICIT NonCopyable(NonCopyable const &) = delete; +struct NonCopyable : DEFINE_BASE(NonCopyable) { + using Base = DEFINE_BASE(NonCopyable); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR NonCopyable() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR NonCopyable(NonCopyable const &) = delete; NonCopyable &operator=(NonCopyable const &) = delete; DEFINE_DTOR(NonCopyable) }; -struct MoveOnly { - DEFINE_EXPLICIT MoveOnly() DEFINE_CTOR; - DEFINE_EXPLICIT MoveOnly(MoveOnly &&) DEFINE_CTOR; +struct MoveOnly : DEFINE_BASE(MoveOnly) { + using Base = DEFINE_BASE(MoveOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveOnly() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveOnly(MoveOnly &&) DEFINE_CTOR; MoveOnly &operator=(MoveOnly &&) DEFINE_ASSIGN; DEFINE_DTOR(MoveOnly) }; -struct CopyAssignable { - DEFINE_EXPLICIT CopyAssignable() = delete; - CopyAssignable& operator=(CopyAssignable const&) DEFINE_ASSIGN; - DEFINE_DTOR(CopyAssignable) +struct CopyAssignable : DEFINE_BASE(CopyAssignable) { + using Base = DEFINE_BASE(CopyAssignable); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyAssignable() = delete; + CopyAssignable& operator=(CopyAssignable const&) DEFINE_ASSIGN; + DEFINE_DTOR(CopyAssignable) }; -struct CopyAssignOnly { - DEFINE_EXPLICIT CopyAssignOnly() = delete; - CopyAssignOnly& operator=(CopyAssignOnly const&) DEFINE_ASSIGN; - CopyAssignOnly& operator=(CopyAssignOnly &&) = delete; - DEFINE_DTOR(CopyAssignOnly) +struct CopyAssignOnly : DEFINE_BASE(CopyAssignOnly) { + using Base = DEFINE_BASE(CopyAssignOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyAssignOnly() = delete; + CopyAssignOnly& operator=(CopyAssignOnly const&) DEFINE_ASSIGN; + CopyAssignOnly& operator=(CopyAssignOnly &&) = delete; + DEFINE_DTOR(CopyAssignOnly) }; -struct MoveAssignOnly { - DEFINE_EXPLICIT MoveAssignOnly() = delete; - MoveAssignOnly& operator=(MoveAssignOnly const&) = delete; - MoveAssignOnly& operator=(MoveAssignOnly &&) DEFINE_ASSIGN; - DEFINE_DTOR(MoveAssignOnly) +struct MoveAssignOnly : DEFINE_BASE(MoveAssignOnly) { + using Base = DEFINE_BASE(MoveAssignOnly); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveAssignOnly() = delete; + MoveAssignOnly& operator=(MoveAssignOnly const&) = delete; + MoveAssignOnly& operator=(MoveAssignOnly &&) DEFINE_ASSIGN; + DEFINE_DTOR(MoveAssignOnly) }; -struct ConvertingType { - DEFINE_EXPLICIT ConvertingType() DEFINE_CTOR; - DEFINE_EXPLICIT ConvertingType(ConvertingType const&) DEFINE_CTOR; - DEFINE_EXPLICIT ConvertingType(ConvertingType &&) DEFINE_CTOR; +struct ConvertingType : DEFINE_BASE(ConvertingType) { + using Base = DEFINE_BASE(ConvertingType); + using Base::Base; + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType() DEFINE_DEFAULT_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(ConvertingType const&) DEFINE_CTOR; + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(ConvertingType &&) DEFINE_CTOR; ConvertingType& operator=(ConvertingType const&) DEFINE_ASSIGN; ConvertingType& operator=(ConvertingType &&) DEFINE_ASSIGN; template <class ...Args> - DEFINE_EXPLICIT ConvertingType(Args&&...) {} + DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(Args&&...) {} template <class Arg> ConvertingType& operator=(Arg&&) { return *this; } DEFINE_DTOR(ConvertingType) @@ -91,8 +142,10 @@ struct ConvertingType { template <template <class...> class List> using ApplyTypes = List< - NoDefault, AllCtors, + NoCtors, + NoDefault, + DefaultOnly, Copyable, CopyOnly, NonCopyable, @@ -103,7 +156,11 @@ using ApplyTypes = List< ConvertingType >; +#undef DEFINE_BASE #undef DEFINE_EXPLICIT +#undef DEFINE_CONSTEXPR +#undef DEFINE_ASSIGN_CONSTEXPR #undef DEFINE_CTOR +#undef DEFINE_DEFAULT_CTOR #undef DEFINE_ASSIGN #undef DEFINE_DTOR |