mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 13:50:11 +00:00
[libc++] Implement std::expected
P0323R12
Implement `std::expected` https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0323r12.html Added tests Differential Revision: https://reviews.llvm.org/D124516 address comment
This commit is contained in:
parent
e6b9fc4c8b
commit
e356f681f6
@ -318,6 +318,8 @@ Status
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_constexpr_typeinfo`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_expected`` ``202202L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_forward_like`` ``202207L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_invoke_r`` *unimplemented*
|
||||
|
@ -167,11 +167,11 @@
|
||||
"`3671 <https://wg21.link/LWG3671>`__","``atomic_fetch_xor`` missing from ``stdatomic.h``","July 2022","",""
|
||||
"`3672 <https://wg21.link/LWG3672>`__","``common_iterator::operator->()`` should return by value","July 2022","","","|ranges|"
|
||||
"`3683 <https://wg21.link/LWG3683>`__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","",""
|
||||
"`3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","July 2022","",""
|
||||
"`3687 <https://wg21.link/LWG3687>`__","``expected<cv void, E>`` move constructor should move","July 2022","Complete","16.0"
|
||||
"`3692 <https://wg21.link/LWG3692>`__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|ranges| |spaceship|"
|
||||
"`3701 <https://wg21.link/LWG3701>`__","Make ``formatter<remove_cvref_t<const charT[N]>, charT>`` requirement explicit","July 2022","","","|format|"
|
||||
"`3702 <https://wg21.link/LWG3702>`__","Should ``zip_transform_view::iterator`` remove ``operator<``","July 2022","","","|ranges| |spaceship|"
|
||||
"`3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","July 2022","",""
|
||||
"`3703 <https://wg21.link/LWG3703>`__","Missing requirements for ``expected<T, E>`` requires ``is_void<T>``","July 2022","Complete","16.0"
|
||||
"`3704 <https://wg21.link/LWG3704>`__","LWG 2059 added overloads that might be ill-formed for sets","July 2022","",""
|
||||
"`3705 <https://wg21.link/LWG3705>`__","Hashability shouldn't depend on basic_string's allocator","July 2022","|Complete|","16.0"
|
||||
"`3707 <https://wg21.link/LWG3707>`__","chunk_view::outer-iterator::value_type::size should return unsigned type","July 2022","","","|ranges|"
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -38,7 +38,7 @@
|
||||
"`P2393R1 <https://wg21.link/P2393R1>`__","LWG","Cleaning up ``integer``-class types","October 2021","",""
|
||||
"`P2401R0 <https://wg21.link/P2401R0>`__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","|Complete|","14.0"
|
||||
"","","","","",""
|
||||
"`P0323R12 <https://wg21.link/P0323R12>`__","LWG","``std::expected``","February 2022","",""
|
||||
"`P0323R12 <https://wg21.link/P0323R12>`__","LWG","``std::expected``","February 2022","|Complete|","16.0"
|
||||
"`P0533R9 <https://wg21.link/P0533R9>`__","LWG","``constexpr`` for ``<cmath>`` and ``<cstdlib>``","February 2022","",""
|
||||
"`P0627R6 <https://wg21.link/P0627R6>`__","LWG","Function to mark unreachable code","February 2022","|Complete|","15.0"
|
||||
"`P1206R7 <https://wg21.link/P1206R7>`__","LWG","``ranges::to``: A function to convert any range to a container","February 2022","","","|ranges|"
|
||||
@ -86,7 +86,7 @@
|
||||
"`P2517R1 <https://wg21.link/P2517R1>`__","LWG","Add a conditional ``noexcept`` specification to ``std::apply``","July 2022","",""
|
||||
"`P2520R0 <https://wg21.link/P2520R0>`__","LWG","``move_iterator`` should be a random access iterator","July 2022","","","|ranges|"
|
||||
"`P2540R1 <https://wg21.link/P2540R1>`__","LWG","Empty Product for certain Views","July 2022","","","|ranges|"
|
||||
"`P2549R1 <https://wg21.link/P2549R1>`__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","",""
|
||||
"`P2549R1 <https://wg21.link/P2549R1>`__","LWG","``std::unexpected`` should have ``error()`` as member accessor","July 2022","|Complete|","16.0"
|
||||
"`P2553R1 <https://wg21.link/P2553R1>`__","LWG","Make ``mdspan`` ``size_type`` controllable","July 2022","",""
|
||||
"`P2554R0 <https://wg21.link/P2554R0>`__","LWG","C-Array Interoperability of MDSpan","July 2022","",""
|
||||
"`P2585R0 <https://wg21.link/P2585R0>`__","LWG","Improving default container formatting","July 2022","",""
|
||||
|
Can't render this file because it has a wrong number of fields in line 2.
|
@ -269,6 +269,10 @@ set(files
|
||||
__debug
|
||||
__debug_utils/randomize_range.h
|
||||
__errc
|
||||
__expected/bad_expected_access.h
|
||||
__expected/expected.h
|
||||
__expected/unexpect.h
|
||||
__expected/unexpected.h
|
||||
__filesystem/copy_options.h
|
||||
__filesystem/directory_entry.h
|
||||
__filesystem/directory_iterator.h
|
||||
@ -740,6 +744,7 @@ set(files
|
||||
errno.h
|
||||
exception
|
||||
execution
|
||||
expected
|
||||
experimental/__config
|
||||
experimental/__memory
|
||||
experimental/algorithm
|
||||
|
64
libcxx/include/__expected/bad_expected_access.h
Normal file
64
libcxx/include/__expected/bad_expected_access.h
Normal file
@ -0,0 +1,64 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H
|
||||
#define _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H
|
||||
|
||||
#include <__config>
|
||||
#include <__utility/move.h>
|
||||
|
||||
#include <exception>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Err>
|
||||
class bad_expected_access;
|
||||
|
||||
template <>
|
||||
class bad_expected_access<void> : public exception {
|
||||
protected:
|
||||
_LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default;
|
||||
_LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) = default;
|
||||
_LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default;
|
||||
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default;
|
||||
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default;
|
||||
~bad_expected_access() override = default;
|
||||
|
||||
public:
|
||||
// The way this has been designed (by using a class template below) means that we'll already
|
||||
// have a profusion of these vtables in TUs, and the dynamic linker will already have a bunch
|
||||
// of work to do. So it is not worth hiding the <void> specialization in the dylib, given that
|
||||
// it adds deployment target restrictions.
|
||||
const char* what() const noexcept override { return "bad access to std::expected"; }
|
||||
};
|
||||
|
||||
template <class _Err>
|
||||
class bad_expected_access : public bad_expected_access<void> {
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI explicit bad_expected_access(_Err __e) : __unex_(std::move(__e)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _Err& error() & noexcept { return __unex_; }
|
||||
_LIBCPP_HIDE_FROM_ABI const _Err& error() const& noexcept { return __unex_; }
|
||||
_LIBCPP_HIDE_FROM_ABI _Err&& error() && noexcept { return std::move(__unex_); }
|
||||
_LIBCPP_HIDE_FROM_ABI const _Err&& error() const&& noexcept { return std::move(__unex_); }
|
||||
|
||||
private:
|
||||
_Err __unex_;
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
#endif // _LIBCPP___EXPECTED_BAD_EXPECTED_ACCESS_H
|
971
libcxx/include/__expected/expected.h
Normal file
971
libcxx/include/__expected/expected.h
Normal file
@ -0,0 +1,971 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP___EXPECTED_EXPECTED_H
|
||||
#define _LIBCPP___EXPECTED_EXPECTED_H
|
||||
|
||||
#include <__assert>
|
||||
#include <__config>
|
||||
#include <__expected/bad_expected_access.h>
|
||||
#include <__expected/unexpect.h>
|
||||
#include <__expected/unexpected.h>
|
||||
#include <__memory/addressof.h>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__type_traits/conjunction.h>
|
||||
#include <__type_traits/disjunction.h>
|
||||
#include <__type_traits/is_assignable.h>
|
||||
#include <__type_traits/is_constructible.h>
|
||||
#include <__type_traits/is_convertible.h>
|
||||
#include <__type_traits/is_copy_assignable.h>
|
||||
#include <__type_traits/is_copy_constructible.h>
|
||||
#include <__type_traits/is_default_constructible.h>
|
||||
#include <__type_traits/is_function.h>
|
||||
#include <__type_traits/is_move_assignable.h>
|
||||
#include <__type_traits/is_move_constructible.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__type_traits/is_nothrow_copy_assignable.h>
|
||||
#include <__type_traits/is_nothrow_copy_constructible.h>
|
||||
#include <__type_traits/is_nothrow_default_constructible.h>
|
||||
#include <__type_traits/is_nothrow_move_assignable.h>
|
||||
#include <__type_traits/is_nothrow_move_constructible.h>
|
||||
#include <__type_traits/is_reference.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_swappable.h>
|
||||
#include <__type_traits/is_trivially_copy_constructible.h>
|
||||
#include <__type_traits/is_trivially_destructible.h>
|
||||
#include <__type_traits/is_trivially_move_constructible.h>
|
||||
#include <__type_traits/is_void.h>
|
||||
#include <__type_traits/lazy.h>
|
||||
#include <__type_traits/negation.h>
|
||||
#include <__type_traits/remove_cv.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/in_place.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
#include <__utility/transaction.h>
|
||||
#include <cstdlib> // for std::abort
|
||||
#include <initializer_list>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace __expected {
|
||||
|
||||
template <class _Err, class _Arg>
|
||||
_LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
|
||||
# ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw bad_expected_access<_Err>(std::forward<_Arg>(__arg));
|
||||
# else
|
||||
(void)__arg;
|
||||
std::abort();
|
||||
# endif
|
||||
}
|
||||
|
||||
} // namespace __expected
|
||||
|
||||
template <class _Tp, class _Err>
|
||||
class expected {
|
||||
static_assert(
|
||||
!is_reference_v<_Tp> &&
|
||||
!is_function_v<_Tp> &&
|
||||
!is_same_v<remove_cv_t<_Tp>, in_place_t> &&
|
||||
!is_same_v<remove_cv_t<_Tp>, unexpect_t> &&
|
||||
!__unexpected::__is_unexpected<remove_cv_t<_Tp>>::value &&
|
||||
__unexpected::__valid_unexpected<_Err>::value
|
||||
,
|
||||
"[expected.object.general] A program that instantiates the definition of template expected<T, E> for a "
|
||||
"reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a "
|
||||
"specialization of unexpected for the T parameter is ill-formed. A program that instantiates the "
|
||||
"definition of the template expected<T, E> with a type for the E parameter that is not a valid "
|
||||
"template argument for unexpected is ill-formed.");
|
||||
|
||||
template <class _Up, class _OtherErr>
|
||||
friend class expected;
|
||||
|
||||
public:
|
||||
using value_type = _Tp;
|
||||
using error_type = _Err;
|
||||
using unexpected_type = unexpected<_Err>;
|
||||
|
||||
template <class _Up>
|
||||
using rebind = expected<_Up, error_type>;
|
||||
|
||||
// [expected.object.ctor], constructors
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected()
|
||||
noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
|
||||
requires is_default_constructible_v<_Tp>
|
||||
: __has_val_(true) {
|
||||
std::construct_at(std::addressof(__union_.__val_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&)
|
||||
requires(is_copy_constructible_v<_Tp> &&
|
||||
is_copy_constructible_v<_Err> &&
|
||||
is_trivially_copy_constructible_v<_Tp> &&
|
||||
is_trivially_copy_constructible_v<_Err>)
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other)
|
||||
noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
|
||||
requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
|
||||
!(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
|
||||
: __has_val_(__other.__has_val_) {
|
||||
if (__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_);
|
||||
} else {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
|
||||
requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
|
||||
&& is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other)
|
||||
noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
|
||||
requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
|
||||
!(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
|
||||
: __has_val_(__other.__has_val_) {
|
||||
if (__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_));
|
||||
} else {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
|
||||
using __can_convert =
|
||||
_And< is_constructible<_Tp, _UfQual>,
|
||||
is_constructible<_Err, _OtherErrQual>,
|
||||
_Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
|
||||
_Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>,
|
||||
_Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>,
|
||||
_Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>,
|
||||
_Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>,
|
||||
_Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>,
|
||||
_Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>,
|
||||
_Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>,
|
||||
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
|
||||
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
|
||||
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
|
||||
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >;
|
||||
|
||||
|
||||
public:
|
||||
template <class _Up, class _OtherErr>
|
||||
requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> ||
|
||||
!is_convertible_v<const _OtherErr&, _Err>)
|
||||
expected(const expected<_Up, _OtherErr>& __other)
|
||||
noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
|
||||
is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||
: __has_val_(__other.__has_val_) {
|
||||
if (__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_);
|
||||
} else {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Up, class _OtherErr>
|
||||
requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
|
||||
expected(expected<_Up, _OtherErr>&& __other)
|
||||
noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||
: __has_val_(__other.__has_val_) {
|
||||
if (__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_));
|
||||
} else {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Up = _Tp>
|
||||
requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
|
||||
!__unexpected::__is_unexpected<remove_cvref_t<_Up>>::value && is_constructible_v<_Tp, _Up>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
|
||||
expected(_Up&& __u)
|
||||
noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
|
||||
: __has_val_(true) {
|
||||
std::construct_at(std::addressof(__union_.__val_), std::forward<_Up>(__u));
|
||||
}
|
||||
|
||||
|
||||
template <class _OtherErr>
|
||||
requires is_constructible_v<_Err, const _OtherErr&>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
||||
expected(const unexpected<_OtherErr>& __unex)
|
||||
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __unex.error());
|
||||
}
|
||||
|
||||
template <class _OtherErr>
|
||||
requires is_constructible_v<_Err, _OtherErr>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
||||
expected(unexpected<_OtherErr>&& __unex)
|
||||
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
|
||||
}
|
||||
|
||||
template <class... _Args>
|
||||
requires is_constructible_v<_Tp, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
|
||||
noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
|
||||
: __has_val_(true) {
|
||||
std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template <class _Up, class... _Args>
|
||||
requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit
|
||||
expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
|
||||
noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
|
||||
: __has_val_(true) {
|
||||
std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template <class... _Args>
|
||||
requires is_constructible_v<_Err, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
|
||||
noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template <class _Up, class... _Args>
|
||||
requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit
|
||||
expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
|
||||
noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
// [expected.object.dtor], destructor
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~expected()
|
||||
requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~expected()
|
||||
requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
|
||||
{
|
||||
if (__has_val_) {
|
||||
std::destroy_at(std::addressof(__union_.__val_));
|
||||
} else {
|
||||
std::destroy_at(std::addressof(__union_.__unex_));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template <class _T1, class _T2, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) {
|
||||
if constexpr (is_nothrow_constructible_v<_T1, _Args...>) {
|
||||
std::destroy_at(std::addressof(__oldval));
|
||||
std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
|
||||
} else if constexpr (is_nothrow_move_constructible_v<_T1>) {
|
||||
_T1 __tmp(std::forward<_Args>(__args)...);
|
||||
std::destroy_at(std::addressof(__oldval));
|
||||
std::construct_at(std::addressof(__newval), std::move(__tmp));
|
||||
} else {
|
||||
static_assert(
|
||||
is_nothrow_move_constructible_v<_T2>,
|
||||
"To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can "
|
||||
"be reverted to the previous state in case an exception is thrown during the assignment.");
|
||||
_T2 __tmp(std::move(__oldval));
|
||||
std::destroy_at(std::addressof(__oldval));
|
||||
__transaction __trans([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
|
||||
std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
|
||||
__trans.__complete();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// [expected.object.assign], assignment
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs)
|
||||
noexcept(is_nothrow_copy_assignable_v<_Tp> &&
|
||||
is_nothrow_copy_constructible_v<_Tp> &&
|
||||
is_nothrow_copy_assignable_v<_Err> &&
|
||||
is_nothrow_copy_constructible_v<_Err>) // strengthened
|
||||
requires(is_copy_assignable_v<_Tp> &&
|
||||
is_copy_constructible_v<_Tp> &&
|
||||
is_copy_assignable_v<_Err> &&
|
||||
is_copy_constructible_v<_Err> &&
|
||||
(is_nothrow_move_constructible_v<_Tp> ||
|
||||
is_nothrow_move_constructible_v<_Err>))
|
||||
{
|
||||
if (__has_val_ && __rhs.__has_val_) {
|
||||
__union_.__val_ = __rhs.__union_.__val_;
|
||||
} else if (__has_val_) {
|
||||
__reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_);
|
||||
} else if (__rhs.__has_val_) {
|
||||
__reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_);
|
||||
} else {
|
||||
__union_.__unex_ = __rhs.__union_.__unex_;
|
||||
}
|
||||
// note: only reached if no exception+rollback was done inside __reinit_expected
|
||||
__has_val_ = __rhs.__has_val_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs)
|
||||
noexcept(is_nothrow_move_assignable_v<_Tp> &&
|
||||
is_nothrow_move_constructible_v<_Tp> &&
|
||||
is_nothrow_move_assignable_v<_Err> &&
|
||||
is_nothrow_move_constructible_v<_Err>)
|
||||
requires(is_move_constructible_v<_Tp> &&
|
||||
is_move_assignable_v<_Tp> &&
|
||||
is_move_constructible_v<_Err> &&
|
||||
is_move_assignable_v<_Err> &&
|
||||
(is_nothrow_move_constructible_v<_Tp> ||
|
||||
is_nothrow_move_constructible_v<_Err>))
|
||||
{
|
||||
if (__has_val_ && __rhs.__has_val_) {
|
||||
__union_.__val_ = std::move(__rhs.__union_.__val_);
|
||||
} else if (__has_val_) {
|
||||
__reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_));
|
||||
} else if (__rhs.__has_val_) {
|
||||
__reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_));
|
||||
} else {
|
||||
__union_.__unex_ = std::move(__rhs.__union_.__unex_);
|
||||
}
|
||||
// note: only reached if no exception+rollback was done inside __reinit_expected
|
||||
__has_val_ = __rhs.__has_val_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _Up = _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v)
|
||||
requires(!is_same_v<expected, remove_cvref_t<_Up>> &&
|
||||
!__unexpected::__is_unexpected<remove_cvref_t<_Up>>::value &&
|
||||
is_constructible_v<_Tp, _Up> &&
|
||||
is_assignable_v<_Tp&, _Up> &&
|
||||
(is_nothrow_constructible_v<_Tp, _Up> ||
|
||||
is_nothrow_move_constructible_v<_Tp> ||
|
||||
is_nothrow_move_constructible_v<_Err>))
|
||||
{
|
||||
if (__has_val_) {
|
||||
__union_.__val_ = std::forward<_Up>(__v);
|
||||
} else {
|
||||
__reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v));
|
||||
__has_val_ = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template <class _OtherErrQual>
|
||||
static constexpr bool __can_assign_from_unexpected =
|
||||
_And< is_constructible<_Err, _OtherErrQual>,
|
||||
is_assignable<_Err&, _OtherErrQual>,
|
||||
_Lazy<_Or,
|
||||
is_nothrow_constructible<_Err, _OtherErrQual>,
|
||||
is_nothrow_move_constructible<_Tp>,
|
||||
is_nothrow_move_constructible<_Err>> >::value;
|
||||
|
||||
public:
|
||||
template <class _OtherErr>
|
||||
requires(__can_assign_from_unexpected<const _OtherErr&>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
|
||||
if (__has_val_) {
|
||||
__reinit_expected(__union_.__unex_, __union_.__val_, __un.error());
|
||||
__has_val_ = false;
|
||||
} else {
|
||||
__union_.__unex_ = __un.error();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _OtherErr>
|
||||
requires(__can_assign_from_unexpected<_OtherErr>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
|
||||
if (__has_val_) {
|
||||
__reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error()));
|
||||
__has_val_ = false;
|
||||
} else {
|
||||
__union_.__unex_ = std::move(__un.error());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class... _Args>
|
||||
requires is_nothrow_constructible_v<_Tp, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
|
||||
if (__has_val_) {
|
||||
std::destroy_at(std::addressof(__union_.__val_));
|
||||
} else {
|
||||
std::destroy_at(std::addressof(__union_.__unex_));
|
||||
__has_val_ = true;
|
||||
}
|
||||
return *std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template <class _Up, class... _Args>
|
||||
requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
|
||||
if (__has_val_) {
|
||||
std::destroy_at(std::addressof(__union_.__val_));
|
||||
} else {
|
||||
std::destroy_at(std::addressof(__union_.__unex_));
|
||||
__has_val_ = true;
|
||||
}
|
||||
return *std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
// [expected.object.swap], swap
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs)
|
||||
noexcept(is_nothrow_move_constructible_v<_Tp> &&
|
||||
is_nothrow_swappable_v<_Tp> &&
|
||||
is_nothrow_move_constructible_v<_Err> &&
|
||||
is_nothrow_swappable_v<_Err>)
|
||||
requires(is_swappable_v<_Tp> &&
|
||||
is_swappable_v<_Err> &&
|
||||
is_move_constructible_v<_Tp> &&
|
||||
is_move_constructible_v<_Err> &&
|
||||
(is_nothrow_move_constructible_v<_Tp> ||
|
||||
is_nothrow_move_constructible_v<_Err>))
|
||||
{
|
||||
auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
|
||||
if constexpr (is_nothrow_move_constructible_v<_Err>) {
|
||||
_Err __tmp(std::move(__with_err.__union_.__unex_));
|
||||
std::destroy_at(std::addressof(__with_err.__union_.__unex_));
|
||||
__transaction __trans([&] {
|
||||
std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp));
|
||||
});
|
||||
std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_));
|
||||
__trans.__complete();
|
||||
std::destroy_at(std::addressof(__with_val.__union_.__val_));
|
||||
std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp));
|
||||
} else {
|
||||
static_assert(is_nothrow_move_constructible_v<_Tp>,
|
||||
"To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
|
||||
"that it can be reverted to the previous state in case an exception is thrown during swap.");
|
||||
_Tp __tmp(std::move(__with_val.__union_.__val_));
|
||||
std::destroy_at(std::addressof(__with_val.__union_.__val_));
|
||||
__transaction __trans([&] { std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp)); });
|
||||
std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
|
||||
__trans.__complete();
|
||||
std::destroy_at(std::addressof(__with_err.__union_.__unex_));
|
||||
std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp));
|
||||
}
|
||||
__with_val.__has_val_ = false;
|
||||
__with_err.__has_val_ = true;
|
||||
};
|
||||
|
||||
if (__has_val_) {
|
||||
if (__rhs.__has_val_) {
|
||||
using std::swap;
|
||||
swap(__union_.__val_, __rhs.__union_.__val_);
|
||||
} else {
|
||||
__swap_val_unex_impl(*this, __rhs);
|
||||
}
|
||||
} else {
|
||||
if (__rhs.__has_val_) {
|
||||
__swap_val_unex_impl(__rhs, *this);
|
||||
} else {
|
||||
using std::swap;
|
||||
swap(__union_.__unex_, __rhs.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y)
|
||||
noexcept(noexcept(__x.swap(__y)))
|
||||
requires requires { __x.swap(__y); }
|
||||
{
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
// [expected.object.obs], observers
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept {
|
||||
_LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value");
|
||||
return std::addressof(__union_.__val_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
|
||||
_LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value");
|
||||
return std::addressof(__union_.__val_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
|
||||
_LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
|
||||
return __union_.__val_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
|
||||
_LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
|
||||
return __union_.__val_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
|
||||
_LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
|
||||
return std::move(__union_.__val_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
|
||||
_LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
|
||||
return std::move(__union_.__val_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& {
|
||||
if (!__has_val_) {
|
||||
__expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
|
||||
}
|
||||
return __union_.__val_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
|
||||
if (!__has_val_) {
|
||||
__expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
|
||||
}
|
||||
return __union_.__val_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
|
||||
if (!__has_val_) {
|
||||
__expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
|
||||
}
|
||||
return std::move(__union_.__val_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
|
||||
if (!__has_val_) {
|
||||
__expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
|
||||
}
|
||||
return std::move(__union_.__val_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return __union_.__unex_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return __union_.__unex_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return std::move(__union_.__unex_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return std::move(__union_.__unex_);
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
|
||||
static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible");
|
||||
static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
|
||||
return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
|
||||
}
|
||||
|
||||
template <class _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
|
||||
static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible");
|
||||
static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
|
||||
return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
|
||||
}
|
||||
|
||||
// [expected.object.eq], equality operators
|
||||
template <class _T2, class _E2>
|
||||
requires(!is_void_v<_T2>)
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
|
||||
if (__x.__has_val_ != __y.__has_val_) {
|
||||
return false;
|
||||
} else {
|
||||
if (__x.__has_val_) {
|
||||
return __x.__union_.__val_ == __y.__union_.__val_;
|
||||
} else {
|
||||
return __x.__union_.__unex_ == __y.__union_.__unex_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class _T2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
|
||||
return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v);
|
||||
}
|
||||
|
||||
template <class _E2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
|
||||
return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error());
|
||||
}
|
||||
|
||||
private:
|
||||
struct __empty_t {};
|
||||
// use named union because [[no_unique_address]] cannot be applied to an unnamed union
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS union __union_t {
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||
requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
|
||||
= default;
|
||||
|
||||
// the expected's destructor handles this
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||
requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
|
||||
{}
|
||||
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
|
||||
} __union_;
|
||||
|
||||
bool __has_val_;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Err>
|
||||
requires is_void_v<_Tp>
|
||||
class expected<_Tp, _Err> {
|
||||
static_assert(__unexpected::__valid_unexpected<_Err>::value,
|
||||
"[expected.void.general] A program that instantiates expected<T, E> with a E that is not a "
|
||||
"valid argument for unexpected<E> is ill-formed");
|
||||
|
||||
template <class, class>
|
||||
friend class expected;
|
||||
|
||||
template <class _Up, class _OtherErr, class _OtherErrQual>
|
||||
using __can_convert =
|
||||
_And< is_void<_Up>,
|
||||
is_constructible<_Err, _OtherErrQual>,
|
||||
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
|
||||
_Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
|
||||
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
|
||||
_Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>;
|
||||
|
||||
public:
|
||||
using value_type = _Tp;
|
||||
using error_type = _Err;
|
||||
using unexpected_type = unexpected<_Err>;
|
||||
|
||||
template <class _Up>
|
||||
using rebind = expected<_Up, error_type>;
|
||||
|
||||
// [expected.void.ctor], constructors
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&)
|
||||
requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
|
||||
noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
|
||||
requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
|
||||
: __has_val_(__rhs.__has_val_) {
|
||||
if (!__rhs.__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
|
||||
requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
|
||||
noexcept(is_nothrow_move_constructible_v<_Err>)
|
||||
requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
|
||||
: __has_val_(__rhs.__has_val_) {
|
||||
if (!__rhs.__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Up, class _OtherErr>
|
||||
requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
||||
expected(const expected<_Up, _OtherErr>& __rhs)
|
||||
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||
: __has_val_(__rhs.__has_val_) {
|
||||
if (!__rhs.__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Up, class _OtherErr>
|
||||
requires __can_convert<_Up, _OtherErr, _OtherErr>::value
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
||||
expected(expected<_Up, _OtherErr>&& __rhs)
|
||||
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||
: __has_val_(__rhs.__has_val_) {
|
||||
if (!__rhs.__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
|
||||
}
|
||||
}
|
||||
|
||||
template <class _OtherErr>
|
||||
requires is_constructible_v<_Err, const _OtherErr&>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
|
||||
expected(const unexpected<_OtherErr>& __unex)
|
||||
noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __unex.error());
|
||||
}
|
||||
|
||||
template <class _OtherErr>
|
||||
requires is_constructible_v<_Err, _OtherErr>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
|
||||
expected(unexpected<_OtherErr>&& __unex)
|
||||
noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {}
|
||||
|
||||
template <class... _Args>
|
||||
requires is_constructible_v<_Err, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
|
||||
noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
template <class _Up, class... _Args>
|
||||
requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
|
||||
noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
|
||||
: __has_val_(false) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
// [expected.void.dtor], destructor
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~expected()
|
||||
requires is_trivially_destructible_v<_Err>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~expected()
|
||||
requires(!is_trivially_destructible_v<_Err>)
|
||||
{
|
||||
if (!__has_val_) {
|
||||
std::destroy_at(std::addressof(__union_.__unex_));
|
||||
}
|
||||
}
|
||||
|
||||
// [expected.void.assign], assignment
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs)
|
||||
noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened
|
||||
requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>)
|
||||
{
|
||||
if (__has_val_) {
|
||||
if (!__rhs.__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
|
||||
__has_val_ = false;
|
||||
}
|
||||
} else {
|
||||
if (__rhs.__has_val_) {
|
||||
std::destroy_at(std::addressof(__union_.__unex_));
|
||||
__has_val_ = true;
|
||||
} else {
|
||||
__union_.__unex_ = __rhs.__union_.__unex_;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs)
|
||||
noexcept(is_nothrow_move_assignable_v<_Err> &&
|
||||
is_nothrow_move_constructible_v<_Err>)
|
||||
requires(is_move_assignable_v<_Err> &&
|
||||
is_move_constructible_v<_Err>)
|
||||
{
|
||||
if (__has_val_) {
|
||||
if (!__rhs.__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
|
||||
__has_val_ = false;
|
||||
}
|
||||
} else {
|
||||
if (__rhs.__has_val_) {
|
||||
std::destroy_at(std::addressof(__union_.__unex_));
|
||||
__has_val_ = true;
|
||||
} else {
|
||||
__union_.__unex_ = std::move(__rhs.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _OtherErr>
|
||||
requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
|
||||
if (__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), __un.error());
|
||||
__has_val_ = false;
|
||||
} else {
|
||||
__union_.__unex_ = __un.error();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class _OtherErr>
|
||||
requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
|
||||
if (__has_val_) {
|
||||
std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error()));
|
||||
__has_val_ = false;
|
||||
} else {
|
||||
__union_.__unex_ = std::move(__un.error());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
|
||||
if (!__has_val_) {
|
||||
std::destroy_at(std::addressof(__union_.__unex_));
|
||||
__has_val_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
// [expected.void.swap], swap
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs)
|
||||
noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>)
|
||||
requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>)
|
||||
{
|
||||
auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
|
||||
std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
|
||||
std::destroy_at(std::addressof(__with_err.__union_.__unex_));
|
||||
__with_val.__has_val_ = false;
|
||||
__with_err.__has_val_ = true;
|
||||
};
|
||||
|
||||
if (__has_val_) {
|
||||
if (!__rhs.__has_val_) {
|
||||
__swap_val_unex_impl(*this, __rhs);
|
||||
}
|
||||
} else {
|
||||
if (__rhs.__has_val_) {
|
||||
__swap_val_unex_impl(__rhs, *this);
|
||||
} else {
|
||||
using std::swap;
|
||||
swap(__union_.__unex_, __rhs.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y)
|
||||
noexcept(noexcept(__x.swap(__y)))
|
||||
requires requires { __x.swap(__y); }
|
||||
{
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
// [expected.void.obs], observers
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept {
|
||||
_LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
|
||||
if (!__has_val_) {
|
||||
__expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void value() && {
|
||||
if (!__has_val_) {
|
||||
__expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return __union_.__unex_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return __union_.__unex_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return std::move(__union_.__unex_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
|
||||
_LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
|
||||
return std::move(__union_.__unex_);
|
||||
}
|
||||
|
||||
// [expected.void.eq], equality operators
|
||||
template <class _T2, class _E2>
|
||||
requires is_void_v<_T2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
|
||||
if (__x.__has_val_ != __y.__has_val_) {
|
||||
return false;
|
||||
} else {
|
||||
return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _E2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
|
||||
return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error());
|
||||
}
|
||||
|
||||
private:
|
||||
struct __empty_t {};
|
||||
// use named union because [[no_unique_address]] cannot be applied to an unnamed union
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS union __union_t {
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||
requires(is_trivially_destructible_v<_Err>)
|
||||
= default;
|
||||
|
||||
// the expected's destructor handles this
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
|
||||
requires(!is_trivially_destructible_v<_Err>)
|
||||
{}
|
||||
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
|
||||
} __union_;
|
||||
|
||||
bool __has_val_;
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
#endif // _LIBCPP___EXPECTED_EXPECTED_H
|
32
libcxx/include/__expected/unexpect.h
Normal file
32
libcxx/include/__expected/unexpect.h
Normal file
@ -0,0 +1,32 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP___EXPECTED_UNEXPECT_H
|
||||
#define _LIBCPP___EXPECTED_UNEXPECT_H
|
||||
|
||||
#include <__config>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct unexpect_t {
|
||||
_LIBCPP_HIDE_FROM_ABI explicit unexpect_t() = default;
|
||||
};
|
||||
|
||||
inline constexpr unexpect_t unexpect{};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
#endif // _LIBCPP___EXPECTED_UNEXPECT_H
|
126
libcxx/include/__expected/unexpected.h
Normal file
126
libcxx/include/__expected/unexpected.h
Normal file
@ -0,0 +1,126 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP___EXPECTED_UNEXPECTED_H
|
||||
#define _LIBCPP___EXPECTED_UNEXPECTED_H
|
||||
|
||||
#include <__config>
|
||||
#include <__type_traits/conjunction.h>
|
||||
#include <__type_traits/is_array.h>
|
||||
#include <__type_traits/is_const.h>
|
||||
#include <__type_traits/is_constructible.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__type_traits/is_object.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_swappable.h>
|
||||
#include <__type_traits/is_volatile.h>
|
||||
#include <__type_traits/negation.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/in_place.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
#include <initializer_list>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Err>
|
||||
class unexpected;
|
||||
|
||||
namespace __unexpected {
|
||||
|
||||
template <class _Tp>
|
||||
struct __is_unexpected : false_type {};
|
||||
|
||||
template <class _Err>
|
||||
struct __is_unexpected<unexpected<_Err>> : true_type {};
|
||||
|
||||
template <class _Tp>
|
||||
using __valid_unexpected = _BoolConstant< //
|
||||
is_object_v<_Tp> && //
|
||||
!is_array_v<_Tp> && //
|
||||
!__is_unexpected<_Tp>::value && //
|
||||
!is_const_v<_Tp> && //
|
||||
!is_volatile_v<_Tp> //
|
||||
>;
|
||||
|
||||
} // namespace __unexpected
|
||||
|
||||
template <class _Err>
|
||||
class unexpected {
|
||||
static_assert(__unexpected::__valid_unexpected<_Err>::value,
|
||||
"[expected.un.general] states a program that instantiates std::unexpected for a non-object type, an "
|
||||
"array type, a specialization of unexpected, or a cv-qualified type is ill-formed.");
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr unexpected(const unexpected&) = default;
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr unexpected(unexpected&&) = default;
|
||||
|
||||
template <class _Error = _Err>
|
||||
requires(!is_same_v<remove_cvref_t<_Error>, unexpected> && //
|
||||
!is_same_v<remove_cvref_t<_Error>, in_place_t> && //
|
||||
is_constructible_v<_Err, _Error>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(_Error&& __error) //
|
||||
noexcept(is_nothrow_constructible_v<_Err, _Error>) // strengthened
|
||||
: __unex_(std::forward<_Error>(__error)) {}
|
||||
|
||||
template <class... _Args>
|
||||
requires is_constructible_v<_Err, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, _Args&&... __args) //
|
||||
noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
|
||||
: __unex_(std::forward<_Args>(__args)...) {}
|
||||
|
||||
template <class _Up, class... _Args>
|
||||
requires is_constructible_v<_Err, initializer_list<_Up>&, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) //
|
||||
noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
|
||||
: __unex_(__il, std::forward<_Args>(__args)...) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(const unexpected&) = default;
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr unexpected& operator=(unexpected&&) = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { return __unex_; }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { return __unex_; }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { return std::move(__unex_); }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { return std::move(__unex_); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Err>) {
|
||||
static_assert(is_swappable_v<_Err>, "unexpected::swap requires is_swappable_v<E> to be true");
|
||||
using std::swap;
|
||||
swap(__unex_, __other.__unex_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr void swap(unexpected& __x, unexpected& __y) noexcept(noexcept(__x.swap(__y)))
|
||||
requires is_swappable_v<_Err>
|
||||
{
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
template <class _Err2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const unexpected& __x, const unexpected<_Err2>& __y) {
|
||||
return __x.__unex_ == __y.__unex_;
|
||||
}
|
||||
|
||||
private:
|
||||
_Err __unex_;
|
||||
};
|
||||
|
||||
template <class _Err>
|
||||
unexpected(_Err) -> unexpected<_Err>;
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
#endif // _LIBCPP___EXPECTED_UNEXPECTED_H
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <__config>
|
||||
#include <__type_traits/integral_constant.h>
|
||||
#include <__type_traits/is_member_function_pointer.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <__type_traits/is_arithmetic.h>
|
||||
#include <__type_traits/is_enum.h>
|
||||
#include <__type_traits/is_member_pointer.h>
|
||||
#include <__type_traits/is_null_pointer.h>
|
||||
#include <__type_traits/is_pointer.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include <__config>
|
||||
#include <__type_traits/integral_constant.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/remove_cv.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
54
libcxx/include/expected
Normal file
54
libcxx/include/expected
Normal file
@ -0,0 +1,54 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_EXPECTED
|
||||
#define _LIBCPP_EXPECTED
|
||||
|
||||
/*
|
||||
Header <expected> synopsis
|
||||
|
||||
namespace std {
|
||||
// [expected.unexpected], class template unexpected
|
||||
template<class E> class unexpected;
|
||||
|
||||
// [expected.bad], class template bad_expected_access
|
||||
template<class E> class bad_expected_access;
|
||||
|
||||
// [expected.bad.void], specialization for void
|
||||
template<> class bad_expected_access<void>;
|
||||
|
||||
// in-place construction of unexpected values
|
||||
struct unexpect_t {
|
||||
explicit unexpect_t() = default;
|
||||
};
|
||||
inline constexpr unexpect_t unexpect{};
|
||||
|
||||
// [expected.expected], class template expected
|
||||
template<class T, class E> class expected;
|
||||
|
||||
// [expected.void], partial specialization of expected for void types
|
||||
template<class T, class E> requires is_void_v<T> class expected<T, E>;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#include <__assert> // all public C++ headers provide the assertion handler
|
||||
#include <__config>
|
||||
#include <__expected/bad_expected_access.h>
|
||||
#include <__expected/expected.h>
|
||||
#include <__expected/unexpect.h>
|
||||
#include <__expected/unexpected.h>
|
||||
#include <version>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_EXPECTED
|
||||
|
@ -24,6 +24,7 @@
|
||||
{ include: [ "@<__concepts/.*>", "private", "<concepts>", "public" ] },
|
||||
{ include: [ "@<__coroutine/.*>", "private", "<coroutine>", "public" ] },
|
||||
{ include: [ "@<__debug_utils/.*>", "private", "<debug_utils>", "public" ] },
|
||||
{ include: [ "@<__expected/.*>", "private", "<expected>", "public" ] },
|
||||
{ include: [ "@<__filesystem/.*>", "private", "<filesystem>", "public" ] },
|
||||
{ include: [ "@<__format/.*>", "private", "<format>", "public" ] },
|
||||
{ include: [ "@<__functional/.*>", "private", "<functional>", "public" ] },
|
||||
|
@ -785,6 +785,17 @@ module std [system] {
|
||||
header "execution"
|
||||
export *
|
||||
}
|
||||
module expected {
|
||||
header "expected"
|
||||
export *
|
||||
|
||||
module __expected {
|
||||
module bad_expected_access { private header "__expected/bad_expected_access.h" }
|
||||
module expected { private header "__expected/expected.h" }
|
||||
module unexpect { private header "__expected/unexpect.h" }
|
||||
module unexpected { private header "__expected/unexpected.h" }
|
||||
}
|
||||
}
|
||||
module filesystem {
|
||||
@requires_LIBCXX_ENABLE_FILESYSTEM@
|
||||
header "filesystem"
|
||||
|
@ -82,6 +82,7 @@ __cpp_lib_erase_if 202002L <deque> <forward
|
||||
__cpp_lib_exchange_function 201304L <utility>
|
||||
__cpp_lib_execution 201902L <execution>
|
||||
201603L // C++17
|
||||
__cpp_lib_expected 202202L <expected>
|
||||
__cpp_lib_filesystem 201703L <filesystem>
|
||||
__cpp_lib_format 202106L <format>
|
||||
__cpp_lib_forward_like 202207L <utility>
|
||||
@ -390,6 +391,7 @@ __cpp_lib_void_t 201411L <type_traits>
|
||||
# undef __cpp_lib_constexpr_memory
|
||||
# define __cpp_lib_constexpr_memory 202202L
|
||||
// # define __cpp_lib_constexpr_typeinfo 202106L
|
||||
# define __cpp_lib_expected 202202L
|
||||
# define __cpp_lib_forward_like 202207L
|
||||
// # define __cpp_lib_invoke_r 202106L
|
||||
# define __cpp_lib_is_scoped_enum 202011L
|
||||
|
@ -306,464 +306,470 @@ int main(int, char**) { return 0; }
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_47
|
||||
#if defined(TEST_47) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
# include <filesystem>
|
||||
// RUN: %{build} -DTEST_46
|
||||
#if defined(TEST_46)
|
||||
# include <expected>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_49
|
||||
#if defined(TEST_49)
|
||||
# include <format>
|
||||
// RUN: %{build} -DTEST_48
|
||||
#if defined(TEST_48) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
# include <filesystem>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_50
|
||||
#if defined(TEST_50)
|
||||
# include <forward_list>
|
||||
# include <format>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_51
|
||||
#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
|
||||
# include <fstream>
|
||||
#if defined(TEST_51)
|
||||
# include <forward_list>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_52
|
||||
#if defined(TEST_52)
|
||||
# include <functional>
|
||||
#if defined(TEST_52) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
|
||||
# include <fstream>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_53
|
||||
#if defined(TEST_53) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <future>
|
||||
#if defined(TEST_53)
|
||||
# include <functional>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_54
|
||||
#if defined(TEST_54)
|
||||
# include <initializer_list>
|
||||
#if defined(TEST_54) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <future>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_56
|
||||
#if defined(TEST_56) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <iomanip>
|
||||
// RUN: %{build} -DTEST_55
|
||||
#if defined(TEST_55)
|
||||
# include <initializer_list>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_57
|
||||
#if defined(TEST_57) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <ios>
|
||||
# include <iomanip>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_58
|
||||
#if defined(TEST_58)
|
||||
# include <iosfwd>
|
||||
#if defined(TEST_58) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <ios>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_59
|
||||
#if defined(TEST_59) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <iostream>
|
||||
#if defined(TEST_59)
|
||||
# include <iosfwd>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_60
|
||||
#if defined(TEST_60) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <istream>
|
||||
# include <iostream>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_61
|
||||
#if defined(TEST_61)
|
||||
# include <iterator>
|
||||
#if defined(TEST_61) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <istream>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_62
|
||||
#if defined(TEST_62) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <latch>
|
||||
#if defined(TEST_62)
|
||||
# include <iterator>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_63
|
||||
#if defined(TEST_63)
|
||||
#if defined(TEST_63) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <latch>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_64
|
||||
#if defined(TEST_64)
|
||||
# include <limits>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_65
|
||||
#if defined(TEST_65)
|
||||
// RUN: %{build} -DTEST_66
|
||||
#if defined(TEST_66)
|
||||
# include <list>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_66
|
||||
#if defined(TEST_66) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
// RUN: %{build} -DTEST_67
|
||||
#if defined(TEST_67) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <locale>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_68
|
||||
#if defined(TEST_68)
|
||||
// RUN: %{build} -DTEST_69
|
||||
#if defined(TEST_69)
|
||||
# include <map>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_70
|
||||
#if defined(TEST_70)
|
||||
# include <memory>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_71
|
||||
#if defined(TEST_71)
|
||||
# include <memory_resource>
|
||||
# include <memory>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_72
|
||||
#if defined(TEST_72) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <mutex>
|
||||
#if defined(TEST_72)
|
||||
# include <memory_resource>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_73
|
||||
#if defined(TEST_73)
|
||||
# include <new>
|
||||
#if defined(TEST_73) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <mutex>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_74
|
||||
#if defined(TEST_74)
|
||||
# include <numbers>
|
||||
# include <new>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_75
|
||||
#if defined(TEST_75)
|
||||
# include <numeric>
|
||||
# include <numbers>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_76
|
||||
#if defined(TEST_76)
|
||||
# include <optional>
|
||||
# include <numeric>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_77
|
||||
#if defined(TEST_77) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <ostream>
|
||||
#if defined(TEST_77)
|
||||
# include <optional>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_78
|
||||
#if defined(TEST_78)
|
||||
# include <queue>
|
||||
#if defined(TEST_78) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <ostream>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_79
|
||||
#if defined(TEST_79)
|
||||
# include <random>
|
||||
# include <queue>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_80
|
||||
#if defined(TEST_80)
|
||||
# include <ranges>
|
||||
# include <random>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_81
|
||||
#if defined(TEST_81)
|
||||
# include <ratio>
|
||||
# include <ranges>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_82
|
||||
#if defined(TEST_82) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <regex>
|
||||
#if defined(TEST_82)
|
||||
# include <ratio>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_83
|
||||
#if defined(TEST_83)
|
||||
# include <scoped_allocator>
|
||||
#if defined(TEST_83) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <regex>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_84
|
||||
#if defined(TEST_84) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <semaphore>
|
||||
#if defined(TEST_84)
|
||||
# include <scoped_allocator>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_85
|
||||
#if defined(TEST_85)
|
||||
#if defined(TEST_85) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <semaphore>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_86
|
||||
#if defined(TEST_86)
|
||||
# include <set>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_87
|
||||
#if defined(TEST_87) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
// RUN: %{build} -DTEST_88
|
||||
#if defined(TEST_88) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <shared_mutex>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_88
|
||||
#if defined(TEST_88)
|
||||
// RUN: %{build} -DTEST_89
|
||||
#if defined(TEST_89)
|
||||
# include <span>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_89
|
||||
#if defined(TEST_89) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
// RUN: %{build} -DTEST_90
|
||||
#if defined(TEST_90) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <sstream>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_90
|
||||
#if defined(TEST_90)
|
||||
// RUN: %{build} -DTEST_91
|
||||
#if defined(TEST_91)
|
||||
# include <stack>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_94
|
||||
#if defined(TEST_94)
|
||||
// RUN: %{build} -DTEST_95
|
||||
#if defined(TEST_95)
|
||||
# include <stdexcept>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_98
|
||||
#if defined(TEST_98) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
// RUN: %{build} -DTEST_99
|
||||
#if defined(TEST_99) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <streambuf>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_99
|
||||
#if defined(TEST_99)
|
||||
// RUN: %{build} -DTEST_100
|
||||
#if defined(TEST_100)
|
||||
# include <string>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_101
|
||||
#if defined(TEST_101)
|
||||
// RUN: %{build} -DTEST_102
|
||||
#if defined(TEST_102)
|
||||
# include <string_view>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_102
|
||||
#if defined(TEST_102) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
// RUN: %{build} -DTEST_103
|
||||
#if defined(TEST_103) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
# include <strstream>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_103
|
||||
#if defined(TEST_103)
|
||||
// RUN: %{build} -DTEST_104
|
||||
#if defined(TEST_104)
|
||||
# include <system_error>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_105
|
||||
#if defined(TEST_105) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <thread>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_106
|
||||
#if defined(TEST_106)
|
||||
# include <tuple>
|
||||
#if defined(TEST_106) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# include <thread>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_107
|
||||
#if defined(TEST_107)
|
||||
# include <type_traits>
|
||||
# include <tuple>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_108
|
||||
#if defined(TEST_108)
|
||||
# include <typeindex>
|
||||
# include <type_traits>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_109
|
||||
#if defined(TEST_109)
|
||||
# include <typeinfo>
|
||||
# include <typeindex>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_111
|
||||
#if defined(TEST_111)
|
||||
# include <unordered_map>
|
||||
// RUN: %{build} -DTEST_110
|
||||
#if defined(TEST_110)
|
||||
# include <typeinfo>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_112
|
||||
#if defined(TEST_112)
|
||||
# include <unordered_set>
|
||||
# include <unordered_map>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_113
|
||||
#if defined(TEST_113)
|
||||
# include <utility>
|
||||
# include <unordered_set>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_114
|
||||
#if defined(TEST_114)
|
||||
# include <valarray>
|
||||
# include <utility>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_115
|
||||
#if defined(TEST_115)
|
||||
# include <variant>
|
||||
# include <valarray>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_116
|
||||
#if defined(TEST_116)
|
||||
# include <vector>
|
||||
# include <variant>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_117
|
||||
#if defined(TEST_117)
|
||||
# include <vector>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_118
|
||||
#if defined(TEST_118)
|
||||
# include <version>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_120
|
||||
#if defined(TEST_120) && __cplusplus >= 201103L
|
||||
// RUN: %{build} -DTEST_121
|
||||
#if defined(TEST_121) && __cplusplus >= 201103L
|
||||
# include <experimental/algorithm>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_121
|
||||
#if defined(TEST_121) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
|
||||
# include <experimental/coroutine>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_122
|
||||
#if defined(TEST_122) && __cplusplus >= 201103L
|
||||
# include <experimental/deque>
|
||||
#if defined(TEST_122) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
|
||||
# include <experimental/coroutine>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_123
|
||||
#if defined(TEST_123) && __cplusplus >= 201103L
|
||||
# include <experimental/forward_list>
|
||||
# include <experimental/deque>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_124
|
||||
#if defined(TEST_124) && __cplusplus >= 201103L
|
||||
# include <experimental/functional>
|
||||
# include <experimental/forward_list>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_125
|
||||
#if defined(TEST_125) && __cplusplus >= 201103L
|
||||
# include <experimental/iterator>
|
||||
# include <experimental/functional>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_126
|
||||
#if defined(TEST_126) && __cplusplus >= 201103L
|
||||
# include <experimental/list>
|
||||
# include <experimental/iterator>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_127
|
||||
#if defined(TEST_127) && __cplusplus >= 201103L
|
||||
# include <experimental/map>
|
||||
# include <experimental/list>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_128
|
||||
#if defined(TEST_128) && __cplusplus >= 201103L
|
||||
# include <experimental/memory_resource>
|
||||
# include <experimental/map>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_129
|
||||
#if defined(TEST_129) && __cplusplus >= 201103L
|
||||
# include <experimental/propagate_const>
|
||||
# include <experimental/memory_resource>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_130
|
||||
#if defined(TEST_130) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
|
||||
# include <experimental/regex>
|
||||
#if defined(TEST_130) && __cplusplus >= 201103L
|
||||
# include <experimental/propagate_const>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_131
|
||||
#if defined(TEST_131) && __cplusplus >= 201103L
|
||||
# include <experimental/set>
|
||||
#if defined(TEST_131) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
|
||||
# include <experimental/regex>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_132
|
||||
#if defined(TEST_132) && __cplusplus >= 201103L
|
||||
# include <experimental/simd>
|
||||
# include <experimental/set>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_133
|
||||
#if defined(TEST_133) && __cplusplus >= 201103L
|
||||
# include <experimental/string>
|
||||
# include <experimental/simd>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_134
|
||||
#if defined(TEST_134) && __cplusplus >= 201103L
|
||||
# include <experimental/type_traits>
|
||||
# include <experimental/string>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_135
|
||||
#if defined(TEST_135) && __cplusplus >= 201103L
|
||||
# include <experimental/unordered_map>
|
||||
# include <experimental/type_traits>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_136
|
||||
#if defined(TEST_136) && __cplusplus >= 201103L
|
||||
# include <experimental/unordered_set>
|
||||
# include <experimental/unordered_map>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_137
|
||||
#if defined(TEST_137) && __cplusplus >= 201103L
|
||||
# include <experimental/utility>
|
||||
# include <experimental/unordered_set>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_138
|
||||
#if defined(TEST_138) && __cplusplus >= 201103L
|
||||
# include <experimental/vector>
|
||||
# include <experimental/utility>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_139
|
||||
#if defined(TEST_139)
|
||||
# include <ext/hash_map>
|
||||
#if defined(TEST_139) && __cplusplus >= 201103L
|
||||
# include <experimental/vector>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_140
|
||||
#if defined(TEST_140)
|
||||
# include <ext/hash_map>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
||||
// RUN: %{build} -DTEST_141
|
||||
#if defined(TEST_141)
|
||||
# include <ext/hash_set>
|
||||
using HandlerType = decltype(std::__libcpp_verbose_abort);
|
||||
#endif
|
||||
|
@ -91,6 +91,7 @@ END-SCRIPT
|
||||
#include <errno.h>
|
||||
#include <exception>
|
||||
#include <execution>
|
||||
#include <expected>
|
||||
#include <fenv.h>
|
||||
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
# include <filesystem>
|
||||
|
@ -93,6 +93,7 @@ END-SCRIPT
|
||||
#include <errno.h>
|
||||
#include <exception>
|
||||
#include <execution>
|
||||
#include <expected>
|
||||
#include <fenv.h>
|
||||
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
# include <filesystem>
|
||||
|
@ -139,6 +139,8 @@ TEST_MACROS();
|
||||
TEST_MACROS();
|
||||
#include <execution>
|
||||
TEST_MACROS();
|
||||
#include <expected>
|
||||
TEST_MACROS();
|
||||
#include <fenv.h>
|
||||
TEST_MACROS();
|
||||
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
|
@ -235,382 +235,386 @@ END-SCRIPT
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_46
|
||||
#if defined(TEST_46)
|
||||
#include <fenv.h>
|
||||
#include <expected>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_47
|
||||
#if defined(TEST_47) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
#include <filesystem>
|
||||
#if defined(TEST_47)
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_48
|
||||
#if defined(TEST_48)
|
||||
#include <float.h>
|
||||
#if defined(TEST_48) && !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
#include <filesystem>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_49
|
||||
#if defined(TEST_49)
|
||||
#include <format>
|
||||
#include <float.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_50
|
||||
#if defined(TEST_50)
|
||||
#include <forward_list>
|
||||
#include <format>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_51
|
||||
#if defined(TEST_51) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
|
||||
#include <fstream>
|
||||
#if defined(TEST_51)
|
||||
#include <forward_list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_52
|
||||
#if defined(TEST_52)
|
||||
#include <functional>
|
||||
#if defined(TEST_52) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && !defined(_LIBCPP_HAS_NO_FSTREAM)
|
||||
#include <fstream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_53
|
||||
#if defined(TEST_53) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <future>
|
||||
#if defined(TEST_53)
|
||||
#include <functional>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_54
|
||||
#if defined(TEST_54)
|
||||
#include <initializer_list>
|
||||
#if defined(TEST_54) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <future>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_55
|
||||
#if defined(TEST_55)
|
||||
#include <inttypes.h>
|
||||
#include <initializer_list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_56
|
||||
#if defined(TEST_56) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <iomanip>
|
||||
#if defined(TEST_56)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_57
|
||||
#if defined(TEST_57) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <ios>
|
||||
#include <iomanip>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_58
|
||||
#if defined(TEST_58)
|
||||
#include <iosfwd>
|
||||
#if defined(TEST_58) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <ios>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_59
|
||||
#if defined(TEST_59) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <iostream>
|
||||
#if defined(TEST_59)
|
||||
#include <iosfwd>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_60
|
||||
#if defined(TEST_60) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <istream>
|
||||
#include <iostream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_61
|
||||
#if defined(TEST_61)
|
||||
#include <iterator>
|
||||
#if defined(TEST_61) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <istream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_62
|
||||
#if defined(TEST_62) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <latch>
|
||||
#if defined(TEST_62)
|
||||
#include <iterator>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_63
|
||||
#if defined(TEST_63)
|
||||
#include <limits>
|
||||
#if defined(TEST_63) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <latch>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_64
|
||||
#if defined(TEST_64)
|
||||
#include <limits.h>
|
||||
#include <limits>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_65
|
||||
#if defined(TEST_65)
|
||||
#include <list>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_66
|
||||
#if defined(TEST_66) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <locale>
|
||||
#if defined(TEST_66)
|
||||
#include <list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_67
|
||||
#if defined(TEST_67) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <locale.h>
|
||||
#include <locale>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_68
|
||||
#if defined(TEST_68)
|
||||
#include <map>
|
||||
#if defined(TEST_68) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <locale.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_69
|
||||
#if defined(TEST_69)
|
||||
#include <math.h>
|
||||
#include <map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_70
|
||||
#if defined(TEST_70)
|
||||
#include <memory>
|
||||
#include <math.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_71
|
||||
#if defined(TEST_71)
|
||||
#include <memory_resource>
|
||||
#include <memory>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_72
|
||||
#if defined(TEST_72) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <mutex>
|
||||
#if defined(TEST_72)
|
||||
#include <memory_resource>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_73
|
||||
#if defined(TEST_73)
|
||||
#include <new>
|
||||
#if defined(TEST_73) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <mutex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_74
|
||||
#if defined(TEST_74)
|
||||
#include <numbers>
|
||||
#include <new>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_75
|
||||
#if defined(TEST_75)
|
||||
#include <numeric>
|
||||
#include <numbers>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_76
|
||||
#if defined(TEST_76)
|
||||
#include <optional>
|
||||
#include <numeric>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_77
|
||||
#if defined(TEST_77) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <ostream>
|
||||
#if defined(TEST_77)
|
||||
#include <optional>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_78
|
||||
#if defined(TEST_78)
|
||||
#include <queue>
|
||||
#if defined(TEST_78) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <ostream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_79
|
||||
#if defined(TEST_79)
|
||||
#include <random>
|
||||
#include <queue>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_80
|
||||
#if defined(TEST_80)
|
||||
#include <ranges>
|
||||
#include <random>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_81
|
||||
#if defined(TEST_81)
|
||||
#include <ratio>
|
||||
#include <ranges>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_82
|
||||
#if defined(TEST_82) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <regex>
|
||||
#if defined(TEST_82)
|
||||
#include <ratio>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_83
|
||||
#if defined(TEST_83)
|
||||
#include <scoped_allocator>
|
||||
#if defined(TEST_83) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <regex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_84
|
||||
#if defined(TEST_84) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <semaphore>
|
||||
#if defined(TEST_84)
|
||||
#include <scoped_allocator>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_85
|
||||
#if defined(TEST_85)
|
||||
#include <set>
|
||||
#if defined(TEST_85) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <semaphore>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_86
|
||||
#if defined(TEST_86)
|
||||
#include <setjmp.h>
|
||||
#include <set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_87
|
||||
#if defined(TEST_87) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <shared_mutex>
|
||||
#if defined(TEST_87)
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_88
|
||||
#if defined(TEST_88)
|
||||
#include <span>
|
||||
#if defined(TEST_88) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <shared_mutex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_89
|
||||
#if defined(TEST_89) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <sstream>
|
||||
#if defined(TEST_89)
|
||||
#include <span>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_90
|
||||
#if defined(TEST_90)
|
||||
#include <stack>
|
||||
#if defined(TEST_90) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <sstream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_91
|
||||
#if defined(TEST_91) && __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <stdatomic.h>
|
||||
#if defined(TEST_91)
|
||||
#include <stack>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_92
|
||||
#if defined(TEST_92)
|
||||
#include <stdbool.h>
|
||||
#if defined(TEST_92) && __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_93
|
||||
#if defined(TEST_93)
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_94
|
||||
#if defined(TEST_94)
|
||||
#include <stdexcept>
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_95
|
||||
#if defined(TEST_95)
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_96
|
||||
#if defined(TEST_96)
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_97
|
||||
#if defined(TEST_97)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_98
|
||||
#if defined(TEST_98) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <streambuf>
|
||||
#if defined(TEST_98)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_99
|
||||
#if defined(TEST_99)
|
||||
#include <string>
|
||||
#if defined(TEST_99) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <streambuf>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_100
|
||||
#if defined(TEST_100)
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_101
|
||||
#if defined(TEST_101)
|
||||
#include <string_view>
|
||||
#include <string.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_102
|
||||
#if defined(TEST_102) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <strstream>
|
||||
#if defined(TEST_102)
|
||||
#include <string_view>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_103
|
||||
#if defined(TEST_103)
|
||||
#include <system_error>
|
||||
#if defined(TEST_103) && !defined(_LIBCPP_HAS_NO_LOCALIZATION)
|
||||
#include <strstream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_104
|
||||
#if defined(TEST_104)
|
||||
#include <tgmath.h>
|
||||
#include <system_error>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_105
|
||||
#if defined(TEST_105) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <thread>
|
||||
#if defined(TEST_105)
|
||||
#include <tgmath.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_106
|
||||
#if defined(TEST_106)
|
||||
#include <tuple>
|
||||
#if defined(TEST_106) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include <thread>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_107
|
||||
#if defined(TEST_107)
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_108
|
||||
#if defined(TEST_108)
|
||||
#include <typeindex>
|
||||
#include <type_traits>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_109
|
||||
#if defined(TEST_109)
|
||||
#include <typeinfo>
|
||||
#include <typeindex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_110
|
||||
#if defined(TEST_110)
|
||||
#include <uchar.h>
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_111
|
||||
#if defined(TEST_111)
|
||||
#include <unordered_map>
|
||||
#include <uchar.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_112
|
||||
#if defined(TEST_112)
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_113
|
||||
#if defined(TEST_113)
|
||||
#include <utility>
|
||||
#include <unordered_set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_114
|
||||
#if defined(TEST_114)
|
||||
#include <valarray>
|
||||
#include <utility>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_115
|
||||
#if defined(TEST_115)
|
||||
#include <variant>
|
||||
#include <valarray>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_116
|
||||
#if defined(TEST_116)
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_117
|
||||
#if defined(TEST_117)
|
||||
#include <version>
|
||||
#include <vector>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_118
|
||||
#if defined(TEST_118) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
|
||||
#include <wchar.h>
|
||||
#if defined(TEST_118)
|
||||
#include <version>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_119
|
||||
#if defined(TEST_119) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
|
||||
#include <wctype.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_120
|
||||
#if defined(TEST_120) && __cplusplus >= 201103L
|
||||
#include <experimental/algorithm>
|
||||
#if defined(TEST_120) && !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
|
||||
#include <wctype.h>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_121
|
||||
#if defined(TEST_121) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
|
||||
#include <experimental/coroutine>
|
||||
#if defined(TEST_121) && __cplusplus >= 201103L
|
||||
#include <experimental/algorithm>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_122
|
||||
#if defined(TEST_122) && __cplusplus >= 201103L
|
||||
#include <experimental/deque>
|
||||
#if defined(TEST_122) && __cplusplus >= 201103L && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES)
|
||||
#include <experimental/coroutine>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_123
|
||||
#if defined(TEST_123) && __cplusplus >= 201103L
|
||||
#include <experimental/forward_list>
|
||||
#include <experimental/deque>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_124
|
||||
#if defined(TEST_124) && __cplusplus >= 201103L
|
||||
#include <experimental/functional>
|
||||
#include <experimental/forward_list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_125
|
||||
#if defined(TEST_125) && __cplusplus >= 201103L
|
||||
#include <experimental/iterator>
|
||||
#include <experimental/functional>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_126
|
||||
#if defined(TEST_126) && __cplusplus >= 201103L
|
||||
#include <experimental/list>
|
||||
#include <experimental/iterator>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_127
|
||||
#if defined(TEST_127) && __cplusplus >= 201103L
|
||||
#include <experimental/map>
|
||||
#include <experimental/list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_128
|
||||
#if defined(TEST_128) && __cplusplus >= 201103L
|
||||
#include <experimental/memory_resource>
|
||||
#include <experimental/map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_129
|
||||
#if defined(TEST_129) && __cplusplus >= 201103L
|
||||
#include <experimental/propagate_const>
|
||||
#include <experimental/memory_resource>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_130
|
||||
#if defined(TEST_130) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
|
||||
#include <experimental/regex>
|
||||
#if defined(TEST_130) && __cplusplus >= 201103L
|
||||
#include <experimental/propagate_const>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_131
|
||||
#if defined(TEST_131) && __cplusplus >= 201103L
|
||||
#include <experimental/set>
|
||||
#if defined(TEST_131) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L
|
||||
#include <experimental/regex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_132
|
||||
#if defined(TEST_132) && __cplusplus >= 201103L
|
||||
#include <experimental/simd>
|
||||
#include <experimental/set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_133
|
||||
#if defined(TEST_133) && __cplusplus >= 201103L
|
||||
#include <experimental/string>
|
||||
#include <experimental/simd>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_134
|
||||
#if defined(TEST_134) && __cplusplus >= 201103L
|
||||
#include <experimental/type_traits>
|
||||
#include <experimental/string>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_135
|
||||
#if defined(TEST_135) && __cplusplus >= 201103L
|
||||
#include <experimental/unordered_map>
|
||||
#include <experimental/type_traits>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_136
|
||||
#if defined(TEST_136) && __cplusplus >= 201103L
|
||||
#include <experimental/unordered_set>
|
||||
#include <experimental/unordered_map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_137
|
||||
#if defined(TEST_137) && __cplusplus >= 201103L
|
||||
#include <experimental/utility>
|
||||
#include <experimental/unordered_set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_138
|
||||
#if defined(TEST_138) && __cplusplus >= 201103L
|
||||
#include <experimental/vector>
|
||||
#include <experimental/utility>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_139
|
||||
#if defined(TEST_139)
|
||||
#include <ext/hash_map>
|
||||
#if defined(TEST_139) && __cplusplus >= 201103L
|
||||
#include <experimental/vector>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_140
|
||||
#if defined(TEST_140)
|
||||
#include <ext/hash_map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -DTEST_141
|
||||
#if defined(TEST_141)
|
||||
#include <ext/hash_set>
|
||||
#endif
|
||||
// GENERATED-MARKER
|
||||
|
@ -212,6 +212,7 @@ END-SCRIPT
|
||||
#include <errno.h>
|
||||
#include <exception>
|
||||
#include <execution>
|
||||
#include <expected>
|
||||
#include <fenv.h>
|
||||
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
# include <filesystem>
|
||||
|
@ -90,6 +90,7 @@ END-SCRIPT
|
||||
#include <errno.h>
|
||||
#include <exception>
|
||||
#include <execution>
|
||||
#include <expected>
|
||||
#include <fenv.h>
|
||||
#if !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
# include <filesystem>
|
||||
|
@ -301,6 +301,10 @@ END-SCRIPT
|
||||
#include <__coroutine/trivial_awaitables.h> // expected-error@*:* {{use of private header from outside its module: '__coroutine/trivial_awaitables.h'}}
|
||||
#include <__debug_utils/randomize_range.h> // expected-error@*:* {{use of private header from outside its module: '__debug_utils/randomize_range.h'}}
|
||||
#include <__errc> // expected-error@*:* {{use of private header from outside its module: '__errc'}}
|
||||
#include <__expected/bad_expected_access.h> // expected-error@*:* {{use of private header from outside its module: '__expected/bad_expected_access.h'}}
|
||||
#include <__expected/expected.h> // expected-error@*:* {{use of private header from outside its module: '__expected/expected.h'}}
|
||||
#include <__expected/unexpect.h> // expected-error@*:* {{use of private header from outside its module: '__expected/unexpect.h'}}
|
||||
#include <__expected/unexpected.h> // expected-error@*:* {{use of private header from outside its module: '__expected/unexpected.h'}}
|
||||
#include <__filesystem/copy_options.h> // expected-error@*:* {{use of private header from outside its module: '__filesystem/copy_options.h'}}
|
||||
#include <__filesystem/directory_entry.h> // expected-error@*:* {{use of private header from outside its module: '__filesystem/directory_entry.h'}}
|
||||
#include <__filesystem/directory_iterator.h> // expected-error@*:* {{use of private header from outside its module: '__filesystem/directory_iterator.h'}}
|
||||
|
@ -249,312 +249,316 @@ END-SCRIPT
|
||||
#if defined(TEST_45)
|
||||
#include <execution>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_47 2> %t/header.filesystem
|
||||
#if defined(TEST_47)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_46 2> %t/header.expected
|
||||
#if defined(TEST_46)
|
||||
#include <expected>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_48 2> %t/header.filesystem
|
||||
#if defined(TEST_48)
|
||||
#include <filesystem>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_49 2> %t/header.format
|
||||
#if defined(TEST_49)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_50 2> %t/header.format
|
||||
#if defined(TEST_50)
|
||||
#include <format>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_50 2> %t/header.forward_list
|
||||
#if defined(TEST_50)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_51 2> %t/header.forward_list
|
||||
#if defined(TEST_51)
|
||||
#include <forward_list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_51 2> %t/header.fstream
|
||||
#if defined(TEST_51)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_52 2> %t/header.fstream
|
||||
#if defined(TEST_52)
|
||||
#include <fstream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_52 2> %t/header.functional
|
||||
#if defined(TEST_52)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_53 2> %t/header.functional
|
||||
#if defined(TEST_53)
|
||||
#include <functional>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_53 2> %t/header.future
|
||||
#if defined(TEST_53)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_54 2> %t/header.future
|
||||
#if defined(TEST_54)
|
||||
#include <future>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_54 2> %t/header.initializer_list
|
||||
#if defined(TEST_54)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_55 2> %t/header.initializer_list
|
||||
#if defined(TEST_55)
|
||||
#include <initializer_list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_56 2> %t/header.iomanip
|
||||
#if defined(TEST_56)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_57 2> %t/header.iomanip
|
||||
#if defined(TEST_57)
|
||||
#include <iomanip>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_57 2> %t/header.ios
|
||||
#if defined(TEST_57)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_58 2> %t/header.ios
|
||||
#if defined(TEST_58)
|
||||
#include <ios>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_58 2> %t/header.iosfwd
|
||||
#if defined(TEST_58)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_59 2> %t/header.iosfwd
|
||||
#if defined(TEST_59)
|
||||
#include <iosfwd>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_59 2> %t/header.iostream
|
||||
#if defined(TEST_59)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_60 2> %t/header.iostream
|
||||
#if defined(TEST_60)
|
||||
#include <iostream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_60 2> %t/header.istream
|
||||
#if defined(TEST_60)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_61 2> %t/header.istream
|
||||
#if defined(TEST_61)
|
||||
#include <istream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_61 2> %t/header.iterator
|
||||
#if defined(TEST_61)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_62 2> %t/header.iterator
|
||||
#if defined(TEST_62)
|
||||
#include <iterator>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_62 2> %t/header.latch
|
||||
#if defined(TEST_62)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_63 2> %t/header.latch
|
||||
#if defined(TEST_63)
|
||||
#include <latch>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_63 2> %t/header.limits
|
||||
#if defined(TEST_63)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_64 2> %t/header.limits
|
||||
#if defined(TEST_64)
|
||||
#include <limits>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_65 2> %t/header.list
|
||||
#if defined(TEST_65)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_66 2> %t/header.list
|
||||
#if defined(TEST_66)
|
||||
#include <list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_66 2> %t/header.locale
|
||||
#if defined(TEST_66)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_67 2> %t/header.locale
|
||||
#if defined(TEST_67)
|
||||
#include <locale>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_68 2> %t/header.map
|
||||
#if defined(TEST_68)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_69 2> %t/header.map
|
||||
#if defined(TEST_69)
|
||||
#include <map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_70 2> %t/header.memory
|
||||
#if defined(TEST_70)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_71 2> %t/header.memory
|
||||
#if defined(TEST_71)
|
||||
#include <memory>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_71 2> %t/header.memory_resource
|
||||
#if defined(TEST_71)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_72 2> %t/header.memory_resource
|
||||
#if defined(TEST_72)
|
||||
#include <memory_resource>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_72 2> %t/header.mutex
|
||||
#if defined(TEST_72)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_73 2> %t/header.mutex
|
||||
#if defined(TEST_73)
|
||||
#include <mutex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_73 2> %t/header.new
|
||||
#if defined(TEST_73)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_74 2> %t/header.new
|
||||
#if defined(TEST_74)
|
||||
#include <new>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_74 2> %t/header.numbers
|
||||
#if defined(TEST_74)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_75 2> %t/header.numbers
|
||||
#if defined(TEST_75)
|
||||
#include <numbers>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_75 2> %t/header.numeric
|
||||
#if defined(TEST_75)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_76 2> %t/header.numeric
|
||||
#if defined(TEST_76)
|
||||
#include <numeric>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_76 2> %t/header.optional
|
||||
#if defined(TEST_76)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_77 2> %t/header.optional
|
||||
#if defined(TEST_77)
|
||||
#include <optional>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_77 2> %t/header.ostream
|
||||
#if defined(TEST_77)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_78 2> %t/header.ostream
|
||||
#if defined(TEST_78)
|
||||
#include <ostream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_78 2> %t/header.queue
|
||||
#if defined(TEST_78)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_79 2> %t/header.queue
|
||||
#if defined(TEST_79)
|
||||
#include <queue>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_79 2> %t/header.random
|
||||
#if defined(TEST_79)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_80 2> %t/header.random
|
||||
#if defined(TEST_80)
|
||||
#include <random>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_80 2> %t/header.ranges
|
||||
#if defined(TEST_80)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_81 2> %t/header.ranges
|
||||
#if defined(TEST_81)
|
||||
#include <ranges>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_81 2> %t/header.ratio
|
||||
#if defined(TEST_81)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_82 2> %t/header.ratio
|
||||
#if defined(TEST_82)
|
||||
#include <ratio>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_82 2> %t/header.regex
|
||||
#if defined(TEST_82)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_83 2> %t/header.regex
|
||||
#if defined(TEST_83)
|
||||
#include <regex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_83 2> %t/header.scoped_allocator
|
||||
#if defined(TEST_83)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_84 2> %t/header.scoped_allocator
|
||||
#if defined(TEST_84)
|
||||
#include <scoped_allocator>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_84 2> %t/header.semaphore
|
||||
#if defined(TEST_84)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_85 2> %t/header.semaphore
|
||||
#if defined(TEST_85)
|
||||
#include <semaphore>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_85 2> %t/header.set
|
||||
#if defined(TEST_85)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_86 2> %t/header.set
|
||||
#if defined(TEST_86)
|
||||
#include <set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_87 2> %t/header.shared_mutex
|
||||
#if defined(TEST_87)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_88 2> %t/header.shared_mutex
|
||||
#if defined(TEST_88)
|
||||
#include <shared_mutex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_88 2> %t/header.span
|
||||
#if defined(TEST_88)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_89 2> %t/header.span
|
||||
#if defined(TEST_89)
|
||||
#include <span>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_89 2> %t/header.sstream
|
||||
#if defined(TEST_89)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_90 2> %t/header.sstream
|
||||
#if defined(TEST_90)
|
||||
#include <sstream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_90 2> %t/header.stack
|
||||
#if defined(TEST_90)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_91 2> %t/header.stack
|
||||
#if defined(TEST_91)
|
||||
#include <stack>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_94 2> %t/header.stdexcept
|
||||
#if defined(TEST_94)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_95 2> %t/header.stdexcept
|
||||
#if defined(TEST_95)
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_98 2> %t/header.streambuf
|
||||
#if defined(TEST_98)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_99 2> %t/header.streambuf
|
||||
#if defined(TEST_99)
|
||||
#include <streambuf>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_99 2> %t/header.string
|
||||
#if defined(TEST_99)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_100 2> %t/header.string
|
||||
#if defined(TEST_100)
|
||||
#include <string>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_101 2> %t/header.string_view
|
||||
#if defined(TEST_101)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_102 2> %t/header.string_view
|
||||
#if defined(TEST_102)
|
||||
#include <string_view>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_102 2> %t/header.strstream
|
||||
#if defined(TEST_102)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_103 2> %t/header.strstream
|
||||
#if defined(TEST_103)
|
||||
#include <strstream>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_103 2> %t/header.system_error
|
||||
#if defined(TEST_103)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_104 2> %t/header.system_error
|
||||
#if defined(TEST_104)
|
||||
#include <system_error>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_105 2> %t/header.thread
|
||||
#if defined(TEST_105)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_106 2> %t/header.thread
|
||||
#if defined(TEST_106)
|
||||
#include <thread>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_106 2> %t/header.tuple
|
||||
#if defined(TEST_106)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_107 2> %t/header.tuple
|
||||
#if defined(TEST_107)
|
||||
#include <tuple>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_107 2> %t/header.type_traits
|
||||
#if defined(TEST_107)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_108 2> %t/header.type_traits
|
||||
#if defined(TEST_108)
|
||||
#include <type_traits>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_108 2> %t/header.typeindex
|
||||
#if defined(TEST_108)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_109 2> %t/header.typeindex
|
||||
#if defined(TEST_109)
|
||||
#include <typeindex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_109 2> %t/header.typeinfo
|
||||
#if defined(TEST_109)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_110 2> %t/header.typeinfo
|
||||
#if defined(TEST_110)
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_111 2> %t/header.unordered_map
|
||||
#if defined(TEST_111)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_112 2> %t/header.unordered_map
|
||||
#if defined(TEST_112)
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_112 2> %t/header.unordered_set
|
||||
#if defined(TEST_112)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_113 2> %t/header.unordered_set
|
||||
#if defined(TEST_113)
|
||||
#include <unordered_set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_113 2> %t/header.utility
|
||||
#if defined(TEST_113)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_114 2> %t/header.utility
|
||||
#if defined(TEST_114)
|
||||
#include <utility>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_114 2> %t/header.valarray
|
||||
#if defined(TEST_114)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_115 2> %t/header.valarray
|
||||
#if defined(TEST_115)
|
||||
#include <valarray>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_115 2> %t/header.variant
|
||||
#if defined(TEST_115)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_116 2> %t/header.variant
|
||||
#if defined(TEST_116)
|
||||
#include <variant>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_116 2> %t/header.vector
|
||||
#if defined(TEST_116)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_117 2> %t/header.vector
|
||||
#if defined(TEST_117)
|
||||
#include <vector>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_117 2> %t/header.version
|
||||
#if defined(TEST_117)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_118 2> %t/header.version
|
||||
#if defined(TEST_118)
|
||||
#include <version>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_120 2> %t/header.experimental_algorithm
|
||||
#if defined(TEST_120)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_121 2> %t/header.experimental_algorithm
|
||||
#if defined(TEST_121)
|
||||
#include <experimental/algorithm>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_121 2> %t/header.experimental_coroutine
|
||||
#if defined(TEST_121)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_122 2> %t/header.experimental_coroutine
|
||||
#if defined(TEST_122)
|
||||
#include <experimental/coroutine>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_122 2> %t/header.experimental_deque
|
||||
#if defined(TEST_122)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_123 2> %t/header.experimental_deque
|
||||
#if defined(TEST_123)
|
||||
#include <experimental/deque>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_123 2> %t/header.experimental_forward_list
|
||||
#if defined(TEST_123)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_124 2> %t/header.experimental_forward_list
|
||||
#if defined(TEST_124)
|
||||
#include <experimental/forward_list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_124 2> %t/header.experimental_functional
|
||||
#if defined(TEST_124)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_125 2> %t/header.experimental_functional
|
||||
#if defined(TEST_125)
|
||||
#include <experimental/functional>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_125 2> %t/header.experimental_iterator
|
||||
#if defined(TEST_125)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_126 2> %t/header.experimental_iterator
|
||||
#if defined(TEST_126)
|
||||
#include <experimental/iterator>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_126 2> %t/header.experimental_list
|
||||
#if defined(TEST_126)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_127 2> %t/header.experimental_list
|
||||
#if defined(TEST_127)
|
||||
#include <experimental/list>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_127 2> %t/header.experimental_map
|
||||
#if defined(TEST_127)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_128 2> %t/header.experimental_map
|
||||
#if defined(TEST_128)
|
||||
#include <experimental/map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_128 2> %t/header.experimental_memory_resource
|
||||
#if defined(TEST_128)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_129 2> %t/header.experimental_memory_resource
|
||||
#if defined(TEST_129)
|
||||
#include <experimental/memory_resource>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_129 2> %t/header.experimental_propagate_const
|
||||
#if defined(TEST_129)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_130 2> %t/header.experimental_propagate_const
|
||||
#if defined(TEST_130)
|
||||
#include <experimental/propagate_const>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_130 2> %t/header.experimental_regex
|
||||
#if defined(TEST_130)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_131 2> %t/header.experimental_regex
|
||||
#if defined(TEST_131)
|
||||
#include <experimental/regex>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_131 2> %t/header.experimental_set
|
||||
#if defined(TEST_131)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_132 2> %t/header.experimental_set
|
||||
#if defined(TEST_132)
|
||||
#include <experimental/set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_132 2> %t/header.experimental_simd
|
||||
#if defined(TEST_132)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_133 2> %t/header.experimental_simd
|
||||
#if defined(TEST_133)
|
||||
#include <experimental/simd>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_133 2> %t/header.experimental_string
|
||||
#if defined(TEST_133)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_134 2> %t/header.experimental_string
|
||||
#if defined(TEST_134)
|
||||
#include <experimental/string>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_134 2> %t/header.experimental_type_traits
|
||||
#if defined(TEST_134)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_135 2> %t/header.experimental_type_traits
|
||||
#if defined(TEST_135)
|
||||
#include <experimental/type_traits>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_135 2> %t/header.experimental_unordered_map
|
||||
#if defined(TEST_135)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_136 2> %t/header.experimental_unordered_map
|
||||
#if defined(TEST_136)
|
||||
#include <experimental/unordered_map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_136 2> %t/header.experimental_unordered_set
|
||||
#if defined(TEST_136)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_137 2> %t/header.experimental_unordered_set
|
||||
#if defined(TEST_137)
|
||||
#include <experimental/unordered_set>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_137 2> %t/header.experimental_utility
|
||||
#if defined(TEST_137)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_138 2> %t/header.experimental_utility
|
||||
#if defined(TEST_138)
|
||||
#include <experimental/utility>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_138 2> %t/header.experimental_vector
|
||||
#if defined(TEST_138)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_139 2> %t/header.experimental_vector
|
||||
#if defined(TEST_139)
|
||||
#include <experimental/vector>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_139 2> %t/header.ext_hash_map
|
||||
#if defined(TEST_139)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_140 2> %t/header.ext_hash_map
|
||||
#if defined(TEST_140)
|
||||
#include <ext/hash_map>
|
||||
#endif
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_140 2> %t/header.ext_hash_set
|
||||
#if defined(TEST_140)
|
||||
// RUN: %{cxx} %s %{flags} %{compile_flags} --trace-includes -fshow-skipped-includes -fsyntax-only -DTEST_141 2> %t/header.ext_hash_set
|
||||
#if defined(TEST_141)
|
||||
#include <ext/hash_set>
|
||||
#endif
|
||||
// RUN: %{python} %S/transitive_includes_to_csv.py %t > %t/transitive_includes.csv
|
||||
|
@ -202,6 +202,13 @@ exception cstdlib
|
||||
exception type_traits
|
||||
exception version
|
||||
execution version
|
||||
expected cstddef
|
||||
expected cstdlib
|
||||
expected exception
|
||||
expected initializer_list
|
||||
expected new
|
||||
expected type_traits
|
||||
expected version
|
||||
experimental/algorithm algorithm
|
||||
experimental/algorithm cstddef
|
||||
experimental/algorithm type_traits
|
||||
|
|
@ -202,6 +202,13 @@ exception cstdlib
|
||||
exception type_traits
|
||||
exception version
|
||||
execution version
|
||||
expected cstddef
|
||||
expected cstdlib
|
||||
expected exception
|
||||
expected initializer_list
|
||||
expected new
|
||||
expected type_traits
|
||||
expected version
|
||||
experimental/algorithm algorithm
|
||||
experimental/algorithm cstddef
|
||||
experimental/algorithm type_traits
|
||||
|
|
@ -202,6 +202,13 @@ exception cstdlib
|
||||
exception type_traits
|
||||
exception version
|
||||
execution version
|
||||
expected cstddef
|
||||
expected cstdlib
|
||||
expected exception
|
||||
expected initializer_list
|
||||
expected new
|
||||
expected type_traits
|
||||
expected version
|
||||
experimental/algorithm algorithm
|
||||
experimental/algorithm cstddef
|
||||
experimental/algorithm type_traits
|
||||
|
|
@ -202,6 +202,13 @@ exception cstdlib
|
||||
exception type_traits
|
||||
exception version
|
||||
execution version
|
||||
expected cstddef
|
||||
expected cstdlib
|
||||
expected exception
|
||||
expected initializer_list
|
||||
expected new
|
||||
expected type_traits
|
||||
expected version
|
||||
experimental/algorithm algorithm
|
||||
experimental/algorithm cstddef
|
||||
experimental/algorithm type_traits
|
||||
|
|
@ -214,6 +214,13 @@ exception cstdlib
|
||||
exception type_traits
|
||||
exception version
|
||||
execution version
|
||||
expected cstddef
|
||||
expected cstdlib
|
||||
expected exception
|
||||
expected initializer_list
|
||||
expected new
|
||||
expected type_traits
|
||||
expected version
|
||||
experimental/algorithm algorithm
|
||||
experimental/algorithm cstddef
|
||||
experimental/algorithm type_traits
|
||||
|
|
@ -168,6 +168,13 @@ exception cstdlib
|
||||
exception type_traits
|
||||
exception version
|
||||
execution version
|
||||
expected cstddef
|
||||
expected cstdlib
|
||||
expected exception
|
||||
expected initializer_list
|
||||
expected new
|
||||
expected type_traits
|
||||
expected version
|
||||
experimental/algorithm algorithm
|
||||
experimental/algorithm cstddef
|
||||
experimental/algorithm type_traits
|
||||
|
|
@ -0,0 +1,30 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
|
||||
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
|
||||
|
||||
// constexpr const T* operator->() const noexcept;
|
||||
// constexpr T* operator->() noexcept;
|
||||
//
|
||||
// Preconditions: has_value() is true.
|
||||
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
std::expected<int, int> e{std::unexpect, 5};
|
||||
TEST_LIBCPP_ASSERT_FAILURE(e.operator->(), "expected::operator-> requires the expected to contain a value");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(std::as_const(e).operator->(), "expected::operator-> requires the expected to contain a value");
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
|
||||
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
|
||||
|
||||
// constexpr const T& operator*() const & noexcept;
|
||||
// constexpr T& operator*() & noexcept;
|
||||
// constexpr T&& operator*() && noexcept;
|
||||
// constexpr const T&& operator*() const && noexcept;
|
||||
//
|
||||
// Preconditions: has_value() is true.
|
||||
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
std::expected<int, int> e{std::unexpect, 5};
|
||||
TEST_LIBCPP_ASSERT_FAILURE(*e, "expected::operator* requires the expected to contain a value");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(*std::as_const(e), "expected::operator* requires the expected to contain a value");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(*std::move(e), "expected::operator* requires the expected to contain a value");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(*std::move(std::as_const(e)), "expected::operator* requires the expected to contain a value");
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
|
||||
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
|
||||
|
||||
// constexpr const E& error() const & noexcept;
|
||||
// constexpr E& error() & noexcept;
|
||||
// constexpr E&& error() && noexcept;
|
||||
// constexpr const E&& error() const && noexcept;
|
||||
//
|
||||
// Preconditions: has_value() is false.
|
||||
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
std::expected<int, int> e{std::in_place, 5};
|
||||
TEST_LIBCPP_ASSERT_FAILURE(e.error(), "expected::error requires the expected to contain an error");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(std::as_const(e).error(), "expected::error requires the expected to contain an error");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(std::move(e).error(), "expected::error requires the expected to contain an error");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(std::move(std::as_const(e)).error(), "expected::error requires the expected to contain an error");
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// clang-cl and cl currently don't support [[no_unique_address]]
|
||||
// XFAIL: msvc
|
||||
|
||||
// test [[no_unique_address]] is applied to the union
|
||||
|
||||
#include <expected>
|
||||
|
||||
struct Empty {};
|
||||
|
||||
static_assert(sizeof(std::expected<Empty, Empty>) == sizeof(bool));
|
@ -0,0 +1,124 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// test libc++ noexcept extensions on operations of std::expected<T, E>
|
||||
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
// expected();
|
||||
static_assert(std::is_nothrow_default_constructible_v<std::expected<int, int>>);
|
||||
static_assert(!std::is_nothrow_default_constructible_v<std::expected<DefaultMayThrow, int>>);
|
||||
|
||||
// expected(const expected&)
|
||||
static_assert(std::is_nothrow_copy_constructible_v<std::expected<int, int>>);
|
||||
static_assert(!std::is_nothrow_copy_constructible_v<std::expected<CopyMayThrow, int>>);
|
||||
static_assert(!std::is_nothrow_copy_constructible_v<std::expected<int, CopyMayThrow>>);
|
||||
|
||||
// expected(const expected<OtherT, OtherE>&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<long, long>,
|
||||
const std::expected<int, int>&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromCopyIntMayThrow, long>,
|
||||
const std::expected<int, int>&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<long, ConvertFromCopyIntMayThrow>,
|
||||
const std::expected<int, int>&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromCopyIntMayThrow, ConvertFromCopyIntMayThrow>, //
|
||||
const std::expected<int, int>&>);
|
||||
|
||||
// expected(expected<OtherT, OtherE>&&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<long, long>,
|
||||
std::expected<int, int>&&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromMoveIntMayThrow, long>,
|
||||
std::expected<int, int>&&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<long, ConvertFromMoveIntMayThrow>,
|
||||
std::expected<int, int>&&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromMoveIntMayThrow, ConvertFromMoveIntMayThrow>, //
|
||||
std::expected<int, int>&&>);
|
||||
|
||||
// expected(U&&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<int, int>,
|
||||
const int&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromCopyIntMayThrow, int>,
|
||||
const int&>);
|
||||
|
||||
// expected(const unexpected<OtherE>&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<int, long>,
|
||||
const std::unexpected<int>&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<int, ConvertFromCopyIntMayThrow>,
|
||||
const std::unexpected<int>&>);
|
||||
|
||||
// expected(unexpected<OtherE>&&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<int, long>,
|
||||
std::unexpected<int>&&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<int, ConvertFromMoveIntMayThrow>,
|
||||
std::unexpected<int>&&>);
|
||||
|
||||
// expected(in_place_t, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<int, int>,
|
||||
std::in_place_t,
|
||||
const int&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromCopyIntMayThrow, int>,
|
||||
std::in_place_t,
|
||||
const int&>);
|
||||
|
||||
// expected(in_place_t, initializer_list<U>, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromInitializerListNoexcept, int>,
|
||||
std::in_place_t,
|
||||
std::initializer_list<int>>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<ConvertFromInitializerListMayThrow, int>,
|
||||
std::in_place_t,
|
||||
std::initializer_list<int>>);
|
||||
|
||||
// expected(unexpect_t, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<int, int>,
|
||||
std::unexpect_t,
|
||||
const int&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<int, ConvertFromCopyIntMayThrow>,
|
||||
std::unexpect_t,
|
||||
const int&>);
|
||||
|
||||
// expected(unexpect_t, initializer_list<U>, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<int, ConvertFromInitializerListNoexcept>,
|
||||
std::unexpect_t,
|
||||
std::initializer_list<int>>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<int, ConvertFromInitializerListMayThrow>,
|
||||
std::unexpect_t,
|
||||
std::initializer_list<int>>);
|
||||
|
||||
// expected& operator=(const expected&)
|
||||
static_assert(std::is_nothrow_copy_assignable_v<std::expected<int, int>>);
|
||||
static_assert(!std::is_nothrow_copy_assignable_v<std::expected<CopyConstructMayThrow, int>>);
|
||||
static_assert(!std::is_nothrow_copy_assignable_v<std::expected<CopyAssignMayThrow, int>>);
|
||||
static_assert(!std::is_nothrow_copy_assignable_v<std::expected<int, CopyConstructMayThrow>>);
|
||||
static_assert(!std::is_nothrow_copy_assignable_v<std::expected<int, CopyAssignMayThrow>>);
|
@ -0,0 +1,66 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
|
||||
|
||||
// Test the mandates
|
||||
// template<class U> constexpr T value_or(U&& v) const &;
|
||||
// Mandates: is_copy_constructible_v<T> is true and is_convertible_v<U, T> is true.
|
||||
|
||||
// template<class U> constexpr T value_or(U&& v) &&;
|
||||
// Mandates: is_move_constructible_v<T> is true and is_convertible_v<U, T> is true.
|
||||
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
struct NonCopyable {
|
||||
NonCopyable(int) {}
|
||||
NonCopyable(const NonCopyable&) = delete;
|
||||
};
|
||||
|
||||
struct NonMovable {
|
||||
NonMovable(int) {}
|
||||
NonMovable(NonMovable&&) = delete;
|
||||
};
|
||||
|
||||
struct NotConvertibleFromInt {};
|
||||
|
||||
void test() {
|
||||
// const & overload
|
||||
// !is_copy_constructible_v<T>,
|
||||
{
|
||||
const std::expected<NonCopyable, int> f1{5};
|
||||
f1.value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NonCopyable, int>::value_or<int>' requested here}}
|
||||
// expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}value_type has to be copy constructible}}
|
||||
}
|
||||
|
||||
// const & overload
|
||||
// !is_convertible_v<U, T>
|
||||
{
|
||||
const std::expected<NotConvertibleFromInt, int> f1{std::in_place};
|
||||
f1.value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NotConvertibleFromInt, int>::value_or<int>' requested here}}
|
||||
//expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}argument has to be convertible to value_type}}
|
||||
}
|
||||
|
||||
// && overload
|
||||
// !is_move_constructible_v<T>,
|
||||
{
|
||||
std::expected<NonMovable, int> f1{5};
|
||||
std::move(f1).value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NonMovable, int>::value_or<int>' requested here}}
|
||||
//expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}value_type has to be move constructible}}
|
||||
}
|
||||
|
||||
// && overload
|
||||
// !is_convertible_v<U, T>
|
||||
{
|
||||
std::expected<NotConvertibleFromInt, int> f1{std::in_place};
|
||||
std::move(f1).value_or(5); // expected-note{{in instantiation of function template specialization 'std::expected<NotConvertibleFromInt, int>::value_or<int>' requested here}}
|
||||
//expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}argument has to be convertible to value_type}}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// A program that instantiates the definition of unexpected for a non-object type, an array type, a specialization of unexpected, or a cv-qualified type is ill-formed.
|
||||
|
||||
#include <expected>
|
||||
|
||||
|
||||
|
||||
template class std::unexpected<int[2]>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
|
||||
|
||||
template class std::unexpected<const int>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
|
||||
|
||||
template class std::unexpected<int&>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
|
||||
|
||||
template class std::unexpected<std::unexpected<int>>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
|
||||
|
||||
template class std::unexpected<volatile int>; // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}[expected.un.general]}}
|
@ -0,0 +1,45 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// test libc++ noexcept extensions on operations of std::unexpected<E>
|
||||
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
// unexpected(Error&&);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::unexpected<int>,
|
||||
const int&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::unexpected<ConvertFromCopyIntMayThrow>,
|
||||
const int&>);
|
||||
|
||||
|
||||
// unexpected(in_place_t, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::unexpected<int>,
|
||||
std::in_place_t,
|
||||
const int&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::unexpected<ConvertFromCopyIntMayThrow>,
|
||||
std::in_place_t,
|
||||
const int&>);
|
||||
|
||||
// unexpected(in_place_t, initializer_list<U>, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::unexpected<ConvertFromInitializerListNoexcept>,
|
||||
std::in_place_t,
|
||||
std::initializer_list<int>>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::unexpected<ConvertFromInitializerListMayThrow>,
|
||||
std::in_place_t,
|
||||
std::initializer_list<int>>);
|
@ -0,0 +1,26 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error
|
||||
|
||||
// Test the mandates
|
||||
// constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v<E>);
|
||||
// Mandates: is_swappable_v<E> is true.
|
||||
|
||||
#include <expected>
|
||||
|
||||
struct Foo {};
|
||||
|
||||
void swap(Foo&, Foo&) = delete;
|
||||
|
||||
void test() {
|
||||
std::unexpected<Foo> f1{Foo{}};
|
||||
f1.swap(f1); // expected-note{{in instantiation of member function 'std::unexpected<Foo>::swap' requested here}}
|
||||
// expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}unexpected::swap requires is_swappable_v<E> to be true}}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
|
||||
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
|
||||
|
||||
// constexpr void operator*() const noexcept;
|
||||
//
|
||||
// Preconditions: has_value() is true.
|
||||
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
std::expected<void, int> e{std::unexpect, 5};
|
||||
TEST_LIBCPP_ASSERT_FAILURE(*e, "expected::operator* requires the expected to contain a value");
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}}
|
||||
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
|
||||
|
||||
// constexpr const E& error() const & noexcept;
|
||||
// constexpr E& error() & noexcept;
|
||||
// constexpr E&& error() && noexcept;
|
||||
// constexpr const E&& error() const && noexcept;
|
||||
//
|
||||
// Preconditions: has_value() is false.
|
||||
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
std::expected<void, int> e{std::in_place};
|
||||
TEST_LIBCPP_ASSERT_FAILURE(e.error(), "expected::error requires the expected to contain an error");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(std::as_const(e).error(), "expected::error requires the expected to contain an error");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(std::move(e).error(), "expected::error requires the expected to contain an error");
|
||||
TEST_LIBCPP_ASSERT_FAILURE(std::move(std::as_const(e)).error(), "expected::error requires the expected to contain an error");
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// clang-cl and cl currently don't support [[no_unique_address]]
|
||||
// XFAIL: msvc
|
||||
|
||||
// test [[no_unique_address]] is applied to the union
|
||||
|
||||
#include <expected>
|
||||
|
||||
struct Empty {};
|
||||
|
||||
static_assert(sizeof(std::expected<void, Empty>) == sizeof(bool));
|
@ -0,0 +1,80 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// test libc++ noexcept extensions on operations of std::expected<void, E>
|
||||
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
// expected(const expected&)
|
||||
static_assert(std::is_nothrow_copy_constructible_v<std::expected<void, int>>);
|
||||
static_assert(!std::is_nothrow_copy_constructible_v<std::expected<void, CopyMayThrow>>);
|
||||
|
||||
|
||||
// expected(const expected<OtherT, OtherE>&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<void, long>,
|
||||
const std::expected<void, int>&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<void, ConvertFromCopyIntMayThrow>,
|
||||
const std::expected<void, int>&>);
|
||||
|
||||
|
||||
// expected(expected<OtherT, OtherE>&&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<void, long>,
|
||||
std::expected<void, int>&&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<void, ConvertFromMoveIntMayThrow>,
|
||||
std::expected<void, int>&&>);
|
||||
|
||||
// expected(const unexpected<OtherE>&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<void, long>,
|
||||
const std::unexpected<int>&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<void, ConvertFromCopyIntMayThrow>,
|
||||
const std::unexpected<int>&>);
|
||||
|
||||
// expected(unexpected<OtherE>&&)
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<void, long>,
|
||||
std::unexpected<int>&&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<void, ConvertFromMoveIntMayThrow>,
|
||||
std::unexpected<int>&&>);
|
||||
|
||||
|
||||
// expected(unexpect_t, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<void, int>,
|
||||
std::unexpect_t,
|
||||
const int&>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<void, ConvertFromCopyIntMayThrow>,
|
||||
std::unexpect_t,
|
||||
const int&>);
|
||||
|
||||
// expected(unexpect_t, initializer_list<U>, _Args&&...);
|
||||
static_assert(std::is_nothrow_constructible_v< //
|
||||
std::expected<void, ConvertFromInitializerListNoexcept>,
|
||||
std::unexpect_t,
|
||||
std::initializer_list<int>>);
|
||||
static_assert(!std::is_nothrow_constructible_v< //
|
||||
std::expected<void, ConvertFromInitializerListMayThrow>,
|
||||
std::unexpect_t,
|
||||
std::initializer_list<int>>);
|
||||
|
||||
// expected& operator=(const expected&)
|
||||
static_assert(std::is_nothrow_copy_assignable_v<std::expected<void, int>>);
|
||||
static_assert(!std::is_nothrow_copy_assignable_v<std::expected<void, CopyConstructMayThrow>>);
|
||||
static_assert(!std::is_nothrow_copy_assignable_v<std::expected<void, CopyAssignMayThrow>>);
|
51
libcxx/test/libcxx/utilities/expected/types.h
Normal file
51
libcxx/test/libcxx/utilities/expected/types.h
Normal file
@ -0,0 +1,51 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TEST_LIBCXX_UTILITIES_EXPECTED_TYPES_H
|
||||
#define TEST_LIBCXX_UTILITIES_EXPECTED_TYPES_H
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
struct DefaultMayThrow {
|
||||
DefaultMayThrow();
|
||||
};
|
||||
|
||||
struct CopyMayThrow {
|
||||
CopyMayThrow(const CopyMayThrow&);
|
||||
};
|
||||
|
||||
struct ConvertFromCopyIntMayThrow {
|
||||
ConvertFromCopyIntMayThrow(const int&);
|
||||
ConvertFromCopyIntMayThrow(int&&) noexcept;
|
||||
};
|
||||
|
||||
struct ConvertFromMoveIntMayThrow {
|
||||
ConvertFromMoveIntMayThrow(const int&) noexcept;
|
||||
ConvertFromMoveIntMayThrow(int&&);
|
||||
};
|
||||
|
||||
struct ConvertFromInitializerListNoexcept {
|
||||
ConvertFromInitializerListNoexcept(std::initializer_list<int>) noexcept;
|
||||
};
|
||||
|
||||
struct ConvertFromInitializerListMayThrow {
|
||||
ConvertFromInitializerListMayThrow(std::initializer_list<int>);
|
||||
};
|
||||
|
||||
struct CopyConstructMayThrow {
|
||||
CopyConstructMayThrow(const CopyConstructMayThrow&);
|
||||
CopyConstructMayThrow& operator=(CopyConstructMayThrow const&) noexcept;
|
||||
};
|
||||
|
||||
struct CopyAssignMayThrow {
|
||||
CopyAssignMayThrow(const CopyAssignMayThrow&) noexcept;
|
||||
CopyAssignMayThrow& operator=(CopyAssignMayThrow const&);
|
||||
};
|
||||
|
||||
|
||||
#endif // TEST_LIBCXX_UTILITIES_EXPECTED_TYPES_H
|
23
libcxx/test/libcxx/utilities/expected/version.pass.cpp
Normal file
23
libcxx/test/libcxx/utilities/expected/version.pass.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <expected>
|
||||
|
||||
#include <expected>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#ifndef _LIBCPP_VERSION
|
||||
#error _LIBCPP_VERSION not defined
|
||||
#endif
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// WARNING: This test was generated by generate_feature_test_macro_components.py
|
||||
// and should not be edited manually.
|
||||
//
|
||||
// clang-format off
|
||||
|
||||
// <expected>
|
||||
|
||||
// Test the feature test macros defined by <expected>
|
||||
|
||||
/* Constant Value
|
||||
__cpp_lib_expected 202202L [C++2b]
|
||||
*/
|
||||
|
||||
#include <expected>
|
||||
#include "test_macros.h"
|
||||
|
||||
#if TEST_STD_VER < 14
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
#elif TEST_STD_VER == 14
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
#elif TEST_STD_VER == 17
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
#elif TEST_STD_VER == 20
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
#elif TEST_STD_VER > 20
|
||||
|
||||
# ifndef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should be defined in c++2b"
|
||||
# endif
|
||||
# if __cpp_lib_expected != 202202L
|
||||
# error "__cpp_lib_expected should have the value 202202L in c++2b"
|
||||
# endif
|
||||
|
||||
#endif // TEST_STD_VER > 20
|
||||
|
@ -76,6 +76,7 @@
|
||||
__cpp_lib_exchange_function 201304L [C++14]
|
||||
__cpp_lib_execution 201603L [C++17]
|
||||
201902L [C++20]
|
||||
__cpp_lib_expected 202202L [C++2b]
|
||||
__cpp_lib_filesystem 201703L [C++17]
|
||||
__cpp_lib_format 202106L [C++20]
|
||||
__cpp_lib_forward_like 202207L [C++2b]
|
||||
@ -416,6 +417,10 @@
|
||||
# error "__cpp_lib_execution should not be defined before c++17"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_filesystem
|
||||
# error "__cpp_lib_filesystem should not be defined before c++17"
|
||||
# endif
|
||||
@ -1059,6 +1064,10 @@
|
||||
# error "__cpp_lib_execution should not be defined before c++17"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_filesystem
|
||||
# error "__cpp_lib_filesystem should not be defined before c++17"
|
||||
# endif
|
||||
@ -1807,6 +1816,10 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)
|
||||
# ifndef __cpp_lib_filesystem
|
||||
# error "__cpp_lib_filesystem should be defined in c++17"
|
||||
@ -2840,6 +2853,10 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should not be defined before c++2b"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)
|
||||
# ifndef __cpp_lib_filesystem
|
||||
# error "__cpp_lib_filesystem should be defined in c++20"
|
||||
@ -4071,6 +4088,13 @@
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef __cpp_lib_expected
|
||||
# error "__cpp_lib_expected should be defined in c++2b"
|
||||
# endif
|
||||
# if __cpp_lib_expected != 202202L
|
||||
# error "__cpp_lib_expected should have the value 202202L in c++2b"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)
|
||||
# ifndef __cpp_lib_filesystem
|
||||
# error "__cpp_lib_filesystem should be defined in c++2b"
|
||||
|
@ -0,0 +1,31 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// explicit bad_expected_access(E e);
|
||||
|
||||
// Effects: Initializes unex with std::move(e).
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "MoveOnly.h"
|
||||
|
||||
// test explicit
|
||||
static_assert(std::convertible_to<int, int>);
|
||||
static_assert(!std::convertible_to<int, std::bad_expected_access<int>>);
|
||||
|
||||
int main(int, char**) {
|
||||
std::bad_expected_access<MoveOnly> b(MoveOnly{3});
|
||||
assert(b.error().get() == 3);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// E& error() & noexcept;
|
||||
// const E& error() const & noexcept;
|
||||
// E&& error() && noexcept;
|
||||
// const E&& error() const && noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
template <class T>
|
||||
concept ErrorNoexcept =
|
||||
requires(T&& t) {
|
||||
{ std::forward<T>(t).error() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!ErrorNoexcept<int>);
|
||||
static_assert(ErrorNoexcept<std::bad_expected_access<int>&>);
|
||||
static_assert(ErrorNoexcept<std::bad_expected_access<int> const&>);
|
||||
static_assert(ErrorNoexcept<std::bad_expected_access<int>&&>);
|
||||
static_assert(ErrorNoexcept<std::bad_expected_access<int> const&&>);
|
||||
|
||||
void test() {
|
||||
// &
|
||||
{
|
||||
std::bad_expected_access<int> e(5);
|
||||
decltype(auto) i = e.error();
|
||||
static_assert(std::same_as<decltype(i), int&>);
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
// const &
|
||||
{
|
||||
const std::bad_expected_access<int> e(5);
|
||||
decltype(auto) i = e.error();
|
||||
static_assert(std::same_as<decltype(i), const int&>);
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
// &&
|
||||
{
|
||||
std::bad_expected_access<int> e(5);
|
||||
decltype(auto) i = std::move(e).error();
|
||||
static_assert(std::same_as<decltype(i), int&&>);
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
// const &&
|
||||
{
|
||||
const std::bad_expected_access<int> e(5);
|
||||
decltype(auto) i = std::move(e).error();
|
||||
static_assert(std::same_as<decltype(i), const int&&>);
|
||||
assert(i == 5);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// const char* what() const noexcept override;
|
||||
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
template <class T>
|
||||
concept WhatNoexcept =
|
||||
requires(const T& t) {
|
||||
{ t.what() } noexcept;
|
||||
};
|
||||
|
||||
struct foo{};
|
||||
|
||||
static_assert(!WhatNoexcept<foo>);
|
||||
static_assert(WhatNoexcept<std::bad_expected_access<int>>);
|
||||
static_assert(WhatNoexcept<std::bad_expected_access<foo>>);
|
@ -0,0 +1,338 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// template<class U = T>
|
||||
// constexpr expected& operator=(U&& v);
|
||||
//
|
||||
// Constraints:
|
||||
// - is_same_v<expected, remove_cvref_t<U>> is false; and
|
||||
// - remove_cvref_t<U> is not a specialization of unexpected; and
|
||||
// - is_constructible_v<T, U> is true; and
|
||||
// - is_assignable_v<T&, U> is true; and
|
||||
// - is_nothrow_constructible_v<T, U> || is_nothrow_move_constructible_v<T> ||
|
||||
// is_nothrow_move_constructible_v<E> is true.
|
||||
//
|
||||
// Effects:
|
||||
// - If has_value() is true, equivalent to: val = std::forward<U>(v);
|
||||
// - Otherwise, equivalent to:
|
||||
// reinit-expected(val, unex, std::forward<U>(v));
|
||||
// has_val = true;
|
||||
// - Returns: *this.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotCopyConstructible {
|
||||
NotCopyConstructible(const NotCopyConstructible&) = delete;
|
||||
NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
|
||||
};
|
||||
|
||||
struct NotCopyAssignable {
|
||||
NotCopyAssignable(const NotCopyAssignable&) = default;
|
||||
NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_assignable_v<std::expected<int, int>&, int>);
|
||||
|
||||
// is_same_v<expected, remove_cvref_t<U>>
|
||||
// it is true because it covered by the copy assignment
|
||||
static_assert(std::is_assignable_v<std::expected<int, int>&, std::expected<int, int>>);
|
||||
|
||||
// remove_cvref_t<U> is a specialization of unexpected
|
||||
// it is true because it covered the unepxected overload
|
||||
static_assert(std::is_assignable_v<std::expected<int, int>&, std::unexpected<int>>);
|
||||
|
||||
// !is_constructible_v<T, U>
|
||||
struct NoCtorFromInt {
|
||||
NoCtorFromInt(int) = delete;
|
||||
NoCtorFromInt& operator=(int);
|
||||
};
|
||||
static_assert(!std::is_assignable_v<std::expected<NoCtorFromInt, int>&, int>);
|
||||
|
||||
// !is_assignable_v<T&, U>
|
||||
struct NoAssignFromInt {
|
||||
explicit NoAssignFromInt(int);
|
||||
NoAssignFromInt& operator=(int) = delete;
|
||||
};
|
||||
static_assert(!std::is_assignable_v<std::expected<NoAssignFromInt, int>&, int>);
|
||||
|
||||
template <bool moveNoexcept, bool convertNoexcept>
|
||||
struct MaybeNoexcept {
|
||||
explicit MaybeNoexcept(int) noexcept(convertNoexcept);
|
||||
MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept);
|
||||
MaybeNoexcept& operator=(MaybeNoexcept&&) = default;
|
||||
MaybeNoexcept& operator=(int);
|
||||
};
|
||||
|
||||
// !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
|
||||
// is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, int>&, int>);
|
||||
|
||||
// is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, true>, MaybeNoexcept<false, false>>&, int>);
|
||||
|
||||
// !is_nothrow_constructible_v<T, U> && is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<true, false>, MaybeNoexcept<false, false>>&, int>);
|
||||
|
||||
// !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, false>>&, int>);
|
||||
|
||||
constexpr bool test() {
|
||||
// If has_value() is true, equivalent to: val = std::forward<U>(v);
|
||||
// Copy
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<Traced, int> e1(std::in_place, oldState, 5);
|
||||
Traced u(newState, 10);
|
||||
decltype(auto) x = (e1 = u);
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
assert(oldState.copyAssignCalled);
|
||||
}
|
||||
|
||||
// If has_value() is true, equivalent to: val = std::forward<U>(v);
|
||||
// Move
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<Traced, int> e1(std::in_place, oldState, 5);
|
||||
Traced u(newState, 10);
|
||||
decltype(auto) x = (e1 = std::move(u));
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
assert(oldState.moveAssignCalled);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to:
|
||||
// reinit-expected(val, unex, std::forward<U>(v));
|
||||
// is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
// copy
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
{
|
||||
BothMayThrow::state oldState{};
|
||||
std::expected<MoveThrowConvNoexcept, BothMayThrow> e1(std::unexpect, oldState, 5);
|
||||
const int i = 10;
|
||||
decltype(auto) x = (e1 = i);
|
||||
static_assert(std::same_as<decltype(x), std::expected<MoveThrowConvNoexcept, BothMayThrow>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e1.value().copiedFromInt);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to:
|
||||
// reinit-expected(val, unex, std::forward<U>(v));
|
||||
// is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
// move
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
{
|
||||
BothMayThrow::state oldState{};
|
||||
std::expected<MoveThrowConvNoexcept, BothMayThrow> e1(std::unexpect, oldState, 5);
|
||||
decltype(auto) x = (e1 = 10);
|
||||
static_assert(std::same_as<decltype(x), std::expected<MoveThrowConvNoexcept, BothMayThrow>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e1.value().movedFromInt);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to:
|
||||
// reinit-expected(val, unex, std::forward<U>(v));
|
||||
// !is_nothrow_constructible_v<T, U> && is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
// copy
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// T tmp(std::forward<Args>(args)...);
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::move(tmp));
|
||||
{
|
||||
BothMayThrow::state oldState{};
|
||||
std::expected<MoveNoexceptConvThrow, BothMayThrow> e1(std::unexpect, oldState, 5);
|
||||
const int i = 10;
|
||||
decltype(auto) x = (e1 = i);
|
||||
static_assert(std::same_as<decltype(x), std::expected<MoveNoexceptConvThrow, BothMayThrow>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!e1.value().copiedFromInt);
|
||||
assert(e1.value().movedFromTmp);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to:
|
||||
// reinit-expected(val, unex, std::forward<U>(v));
|
||||
// !is_nothrow_constructible_v<T, U> && is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
// move
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// T tmp(std::forward<Args>(args)...);
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::move(tmp));
|
||||
{
|
||||
BothMayThrow::state oldState{};
|
||||
std::expected<MoveNoexceptConvThrow, BothMayThrow> e1(std::unexpect, oldState, 5);
|
||||
decltype(auto) x = (e1 = 10);
|
||||
static_assert(std::same_as<decltype(x), std::expected<MoveNoexceptConvThrow, BothMayThrow>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!e1.value().copiedFromInt);
|
||||
assert(e1.value().movedFromTmp);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to:
|
||||
// reinit-expected(val, unex, std::forward<U>(v));
|
||||
// !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
|
||||
// is_nothrow_move_constructible_v<E>
|
||||
// copy
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
{
|
||||
TracedNoexcept::state oldState{};
|
||||
std::expected<BothMayThrow, TracedNoexcept> e1(std::unexpect, oldState, 5);
|
||||
const int i = 10;
|
||||
decltype(auto) x = (e1 = i);
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothMayThrow, TracedNoexcept>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e1.value().copiedFromInt);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to:
|
||||
// reinit-expected(val, unex, std::forward<U>(v));
|
||||
// !is_nothrow_constructible_v<T, U> && !is_nothrow_move_constructible_v<T> &&
|
||||
// is_nothrow_move_constructible_v<E>
|
||||
// move
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
{
|
||||
TracedNoexcept::state oldState{};
|
||||
std::expected<BothMayThrow, TracedNoexcept> e1(std::unexpect, oldState, 5);
|
||||
decltype(auto) x = (e1 = 10);
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothMayThrow, TracedNoexcept>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e1.value().movedFromInt);
|
||||
}
|
||||
|
||||
// Test default template argument.
|
||||
// Without it, the template parameter cannot be deduced from an initializer list
|
||||
{
|
||||
struct Bar {
|
||||
int i;
|
||||
int j;
|
||||
constexpr Bar(int ii, int jj) : i(ii), j(jj) {}
|
||||
};
|
||||
|
||||
std::expected<Bar, int> e({5, 6});
|
||||
e = {7, 8};
|
||||
assert(e.value().i == 7);
|
||||
assert(e.value().j == 8);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
std::expected<ThrowOnConvert, int> e1(std::unexpect, 5);
|
||||
try {
|
||||
e1 = 10;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error() == 5);
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,291 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// constexpr expected& operator=(const expected& rhs);
|
||||
//
|
||||
// Effects:
|
||||
// - If this->has_value() && rhs.has_value() is true, equivalent to val = *rhs.
|
||||
// - Otherwise, if this->has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, rhs.error())
|
||||
// - Otherwise, if rhs.has_value() is true, equivalent to:
|
||||
// reinit-expected(val, unex, *rhs)
|
||||
// - Otherwise, equivalent to unex = rhs.error().
|
||||
//
|
||||
// - Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this;
|
||||
//
|
||||
// Returns: *this.
|
||||
//
|
||||
// Remarks: This operator is defined as deleted unless:
|
||||
// - is_copy_assignable_v<T> is true and
|
||||
// - is_copy_constructible_v<T> is true and
|
||||
// - is_copy_assignable_v<E> is true and
|
||||
// - is_copy_constructible_v<E> is true and
|
||||
// - is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotCopyConstructible {
|
||||
NotCopyConstructible(const NotCopyConstructible&) = delete;
|
||||
NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
|
||||
};
|
||||
|
||||
struct NotCopyAssignable {
|
||||
NotCopyAssignable(const NotCopyAssignable&) = default;
|
||||
NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
|
||||
};
|
||||
|
||||
struct MoveMayThrow {
|
||||
MoveMayThrow(MoveMayThrow const&) = default;
|
||||
MoveMayThrow& operator=(const MoveMayThrow&) = default;
|
||||
MoveMayThrow(MoveMayThrow&&) noexcept(false) {}
|
||||
MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; }
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_copy_assignable_v<std::expected<int, int>>);
|
||||
|
||||
// !is_copy_assignable_v<T>
|
||||
static_assert(!std::is_copy_assignable_v<std::expected<NotCopyAssignable, int>>);
|
||||
|
||||
// !is_copy_constructible_v<T>
|
||||
static_assert(!std::is_copy_assignable_v<std::expected<NotCopyConstructible, int>>);
|
||||
|
||||
// !is_copy_assignable_v<E>
|
||||
static_assert(!std::is_copy_assignable_v<std::expected<int, NotCopyAssignable>>);
|
||||
|
||||
// !is_copy_constructible_v<E>
|
||||
static_assert(!std::is_copy_assignable_v<std::expected<int, NotCopyConstructible>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_copy_assignable_v<std::expected<MoveMayThrow, int>>);
|
||||
|
||||
// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_copy_assignable_v<std::expected<int, MoveMayThrow>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_copy_assignable_v<std::expected<MoveMayThrow, MoveMayThrow>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// If this->has_value() && rhs.has_value() is true, equivalent to val = *rhs.
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<Traced, int> e1(std::in_place, oldState, 5);
|
||||
const std::expected<Traced, int> e2(std::in_place, newState, 10);
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
assert(oldState.copyAssignCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if this->has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, rhs.error())
|
||||
// E move is not noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
//
|
||||
{
|
||||
TracedNoexcept::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<TracedNoexcept, Traced> e1(std::in_place, oldState, 5);
|
||||
const std::expected<TracedNoexcept, Traced> e2(std::unexpect, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
|
||||
assert(!oldState.copyAssignCalled);
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(newState.copyCtorCalled);
|
||||
assert(!newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if this->has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, rhs.error())
|
||||
// E move is noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
//
|
||||
{
|
||||
Traced::state oldState{};
|
||||
TracedNoexcept::state newState{};
|
||||
std::expected<Traced, TracedNoexcept> e1(std::in_place, oldState, 5);
|
||||
const std::expected<Traced, TracedNoexcept> e2(std::unexpect, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
|
||||
assert(!oldState.copyAssignCalled);
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(newState.copyCtorCalled);
|
||||
assert(!newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if rhs.has_value() is true, equivalent to:
|
||||
// reinit-expected(val, unex, *rhs)
|
||||
// T move is not noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
//
|
||||
{
|
||||
TracedNoexcept::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<Traced, TracedNoexcept> e1(std::unexpect, oldState, 5);
|
||||
const std::expected<Traced, TracedNoexcept> e2(std::in_place, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyAssignCalled);
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(newState.copyCtorCalled);
|
||||
assert(!newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if rhs.has_value() is true, equivalent to:
|
||||
// reinit-expected(val, unex, *rhs)
|
||||
// T move is noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
//
|
||||
{
|
||||
Traced::state oldState{};
|
||||
TracedNoexcept::state newState{};
|
||||
std::expected<TracedNoexcept, Traced> e1(std::unexpect, oldState, 5);
|
||||
const std::expected<TracedNoexcept, Traced> e2(std::in_place, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.copyAssignCalled);
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(newState.copyCtorCalled);
|
||||
assert(!newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to unex = rhs.error().
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<int, Traced> e1(std::unexpect, oldState, 5);
|
||||
const std::expected<int, Traced> e2(std::unexpect, newState, 10);
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<int, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
assert(oldState.copyAssignCalled);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct ThrowOnCopyMoveMayThrow {
|
||||
ThrowOnCopyMoveMayThrow() = default;
|
||||
ThrowOnCopyMoveMayThrow(const ThrowOnCopyMoveMayThrow&) { throw Except{}; };
|
||||
ThrowOnCopyMoveMayThrow& operator=(const ThrowOnCopyMoveMayThrow&) = default;
|
||||
ThrowOnCopyMoveMayThrow(ThrowOnCopyMoveMayThrow&&) noexcept(false) {}
|
||||
};
|
||||
|
||||
// assign value throw on copy
|
||||
{
|
||||
std::expected<ThrowOnCopyMoveMayThrow, int> e1(std::unexpect, 5);
|
||||
const std::expected<ThrowOnCopyMoveMayThrow, int> e2(std::in_place);
|
||||
try {
|
||||
e1 = e2;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
// assign error throw on copy
|
||||
{
|
||||
std::expected<int, ThrowOnCopyMoveMayThrow> e1(5);
|
||||
const std::expected<int, ThrowOnCopyMoveMayThrow> e2(std::unexpect);
|
||||
try {
|
||||
e1 = e2;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
assert(e1.value() == 5);
|
||||
}
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,302 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// constexpr expected& operator=(expected&& rhs) noexcept(see below);
|
||||
//
|
||||
// Constraints:
|
||||
// - is_move_constructible_v<T> is true and
|
||||
// - is_move_assignable_v<T> is true and
|
||||
// - is_move_constructible_v<E> is true and
|
||||
// - is_move_assignable_v<E> is true and
|
||||
// - is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
|
||||
//
|
||||
// Effects:
|
||||
// - If this->has_value() && rhs.has_value() is true, equivalent to val = std::move(*rhs).
|
||||
// - Otherwise, if this->has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::move(rhs.error()))
|
||||
// - Otherwise, if rhs.has_value() is true, equivalent to:
|
||||
// reinit-expected(val, unex, std::move(*rhs))
|
||||
// - Otherwise, equivalent to unex = std::move(rhs.error()).
|
||||
// - Then, if no exception was thrown, equivalent to: has_val = rhs.has_value(); return *this;
|
||||
//
|
||||
// Returns: *this.
|
||||
//
|
||||
// Remarks: The exception specification is equivalent to:
|
||||
// is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T> &&
|
||||
// is_nothrow_move_assignable_v<E> && is_nothrow_move_constructible_v<E>
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotMoveConstructible {
|
||||
NotMoveConstructible(NotMoveConstructible&&) = delete;
|
||||
NotMoveConstructible& operator=(NotMoveConstructible&&) = default;
|
||||
};
|
||||
|
||||
struct NotMoveAssignable {
|
||||
NotMoveAssignable(NotMoveAssignable&&) = default;
|
||||
NotMoveAssignable& operator=(NotMoveAssignable&&) = delete;
|
||||
};
|
||||
|
||||
struct MoveCtorMayThrow {
|
||||
MoveCtorMayThrow(MoveCtorMayThrow&&) noexcept(false) {}
|
||||
MoveCtorMayThrow& operator=(MoveCtorMayThrow&&) noexcept = default;
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_move_assignable_v<std::expected<int, int>>);
|
||||
|
||||
// !is_move_assignable_v<T>
|
||||
static_assert(!std::is_move_assignable_v<std::expected<NotMoveAssignable, int>>);
|
||||
|
||||
// !is_move_constructible_v<T>
|
||||
static_assert(!std::is_move_assignable_v<std::expected<NotMoveConstructible, int>>);
|
||||
|
||||
// !is_move_assignable_v<E>
|
||||
static_assert(!std::is_move_assignable_v<std::expected<int, NotMoveAssignable>>);
|
||||
|
||||
// !is_move_constructible_v<E>
|
||||
static_assert(!std::is_move_assignable_v<std::expected<int, NotMoveConstructible>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_move_assignable_v<std::expected<MoveCtorMayThrow, int>>);
|
||||
|
||||
// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_move_assignable_v<std::expected<int, MoveCtorMayThrow>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_move_assignable_v<std::expected<MoveCtorMayThrow, MoveCtorMayThrow>>);
|
||||
|
||||
struct MoveAssignMayThrow {
|
||||
MoveAssignMayThrow(MoveAssignMayThrow&&) noexcept = default;
|
||||
MoveAssignMayThrow& operator=(MoveAssignMayThrow&&) noexcept(false) { return *this; }
|
||||
};
|
||||
|
||||
// Test noexcept
|
||||
static_assert(std::is_nothrow_move_assignable_v<std::expected<int, int>>);
|
||||
|
||||
// !is_nothrow_move_assignable_v<T>
|
||||
static_assert(!std::is_nothrow_move_assignable_v<std::expected<MoveAssignMayThrow, int>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T>
|
||||
static_assert(!std::is_nothrow_move_assignable_v<std::expected<MoveCtorMayThrow, int>>);
|
||||
|
||||
// !is_nothrow_move_assignable_v<E>
|
||||
static_assert(!std::is_nothrow_move_assignable_v<std::expected<int, MoveAssignMayThrow>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_nothrow_move_assignable_v<std::expected<int, MoveCtorMayThrow>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// If this->has_value() && rhs.has_value() is true, equivalent to val = std::move(*rhs).
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<Traced, int> e1(std::in_place, oldState, 5);
|
||||
std::expected<Traced, int> e2(std::in_place, newState, 10);
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, int>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
assert(oldState.moveAssignCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if this->has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, rhs.error())
|
||||
// E move is not noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
//
|
||||
{
|
||||
TracedNoexcept::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<TracedNoexcept, Traced> e1(std::in_place, oldState, 5);
|
||||
std::expected<TracedNoexcept, Traced> e2(std::unexpect, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
|
||||
assert(!oldState.moveAssignCalled);
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!newState.copyCtorCalled);
|
||||
assert(newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if this->has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, rhs.error())
|
||||
// E move is noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
//
|
||||
{
|
||||
Traced::state oldState{};
|
||||
TracedNoexcept::state newState{};
|
||||
std::expected<Traced, TracedNoexcept> e1(std::in_place, oldState, 5);
|
||||
std::expected<Traced, TracedNoexcept> e2(std::unexpect, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!newState.copyCtorCalled);
|
||||
assert(newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if rhs.has_value() is true, equivalent to:
|
||||
// reinit-expected(val, unex, *rhs)
|
||||
// T move is not noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
//
|
||||
{
|
||||
TracedNoexcept::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<Traced, TracedNoexcept> e1(std::unexpect, oldState, 5);
|
||||
std::expected<Traced, TracedNoexcept> e2(std::in_place, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<Traced, TracedNoexcept>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!newState.copyCtorCalled);
|
||||
assert(newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, if rhs.has_value() is true, equivalent to:
|
||||
// reinit-expected(val, unex, *rhs)
|
||||
// T move is noexcept
|
||||
// In this case, it should call the branch
|
||||
//
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
//
|
||||
{
|
||||
Traced::state oldState{};
|
||||
TracedNoexcept::state newState{};
|
||||
std::expected<TracedNoexcept, Traced> e1(std::unexpect, oldState, 5);
|
||||
std::expected<TracedNoexcept, Traced> e2(std::in_place, newState, 10);
|
||||
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<TracedNoexcept, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().data_ == 10);
|
||||
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!oldState.copyCtorCalled);
|
||||
assert(!newState.copyCtorCalled);
|
||||
assert(newState.moveCtorCalled);
|
||||
assert(!newState.dtorCalled);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to unex = rhs.error().
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<int, Traced> e1(std::unexpect, oldState, 5);
|
||||
std::expected<int, Traced> e2(std::unexpect, newState, 10);
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<int, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
assert(oldState.moveAssignCalled);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
// assign value throw on move
|
||||
{
|
||||
std::expected<ThrowOnMoveConstruct, int> e1(std::unexpect, 5);
|
||||
std::expected<ThrowOnMoveConstruct, int> e2(std::in_place);
|
||||
try {
|
||||
e1 = std::move(e2);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
// assign error throw on move
|
||||
{
|
||||
std::expected<int, ThrowOnMoveConstruct> e1(5);
|
||||
std::expected<int, ThrowOnMoveConstruct> e2(std::unexpect);
|
||||
try {
|
||||
e1 = std::move(e2);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
assert(*e1 == 5);
|
||||
}
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// template<class G>
|
||||
// constexpr expected& operator=(const unexpected<G>& e);
|
||||
//
|
||||
// Let GF be const G&
|
||||
// Constraints:
|
||||
// - is_constructible_v<E, GF> is true; and
|
||||
// - is_assignable_v<E&, GF> is true; and
|
||||
// - is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
|
||||
// is_nothrow_move_constructible_v<E> is true.
|
||||
//
|
||||
// Effects:
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// has_val = false;
|
||||
// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
|
||||
// Returns: *this.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotCopyConstructible {
|
||||
NotCopyConstructible(const NotCopyConstructible&) = delete;
|
||||
NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
|
||||
};
|
||||
|
||||
struct NotCopyAssignable {
|
||||
NotCopyAssignable(const NotCopyAssignable&) = default;
|
||||
NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
|
||||
};
|
||||
|
||||
struct MoveMayThrow {
|
||||
MoveMayThrow(MoveMayThrow const&) = default;
|
||||
MoveMayThrow& operator=(const MoveMayThrow&) = default;
|
||||
MoveMayThrow(MoveMayThrow&&) noexcept(false) {}
|
||||
MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; }
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_assignable_v<std::expected<int, int>&, const std::unexpected<int>&>);
|
||||
|
||||
// !is_constructible_v<E, GF>
|
||||
static_assert(
|
||||
!std::is_assignable_v<std::expected<int, NotCopyConstructible>&, const std::unexpected<NotCopyConstructible>&>);
|
||||
|
||||
// !is_assignable_v<E&, GF>
|
||||
static_assert(!std::is_assignable_v<std::expected<int, NotCopyAssignable>&, const std::unexpected<NotCopyAssignable>&>);
|
||||
|
||||
template <bool moveNoexcept, bool convertNoexcept>
|
||||
struct MaybeNoexcept {
|
||||
explicit MaybeNoexcept(int) noexcept(convertNoexcept);
|
||||
MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept);
|
||||
MaybeNoexcept& operator=(MaybeNoexcept&&) = default;
|
||||
MaybeNoexcept& operator=(int);
|
||||
};
|
||||
|
||||
// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
|
||||
// is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<true, false>>&,
|
||||
const std::unexpected<int>&>);
|
||||
|
||||
// is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, true>>&,
|
||||
const std::unexpected<int>&>);
|
||||
|
||||
// !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<true, true>, MaybeNoexcept<false, false>>&,
|
||||
const std::unexpected<int>&>);
|
||||
|
||||
// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, false>>&,
|
||||
const std::unexpected<int>&>);
|
||||
|
||||
constexpr bool test() {
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// is_nothrow_constructible_v<E, GF>
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
{
|
||||
BothNoexcept::state oldState{};
|
||||
std::expected<BothNoexcept, BothNoexcept> e(std::in_place, oldState, 5);
|
||||
const std::unexpected<int> un(10);
|
||||
decltype(auto) x = (e = un);
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothNoexcept>&>);
|
||||
assert(&x == &e);
|
||||
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e.error().copiedFromInt);
|
||||
}
|
||||
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<E>
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// T tmp(std::forward<Args>(args)...);
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::move(tmp));
|
||||
{
|
||||
BothNoexcept::state oldState{};
|
||||
std::expected<BothNoexcept, MoveNoexceptConvThrow> e(std::in_place, oldState, 5);
|
||||
const std::unexpected<int> un(10);
|
||||
decltype(auto) x = (e = un);
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, MoveNoexceptConvThrow>&>);
|
||||
assert(&x == &e);
|
||||
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!e.error().copiedFromInt);
|
||||
assert(e.error().movedFromTmp);
|
||||
}
|
||||
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<E>
|
||||
// is_nothrow_move_constructible_v<T>
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
{
|
||||
BothNoexcept::state oldState{};
|
||||
std::expected<BothNoexcept, BothMayThrow> e(std::in_place, oldState, 5);
|
||||
const std::unexpected<int> un(10);
|
||||
decltype(auto) x = (e = un);
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothMayThrow>&>);
|
||||
assert(&x == &e);
|
||||
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e.error().copiedFromInt);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to: unex = std::forward<GF>(e.error());
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<int, Traced> e1(std::unexpect, oldState, 5);
|
||||
const std::unexpected<Traced> e(std::in_place, newState, 10);
|
||||
decltype(auto) x = (e1 = e);
|
||||
static_assert(std::same_as<decltype(x), std::expected<int, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
assert(oldState.copyAssignCalled);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
std::expected<int, ThrowOnConvert> e1(std::in_place, 5);
|
||||
const std::unexpected<int> un(10);
|
||||
try {
|
||||
e1 = un;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
assert(*e1 == 5);
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// template<class G>
|
||||
// constexpr expected& operator=(unexpected<G>&& e);
|
||||
//
|
||||
// Let GF be G
|
||||
// Constraints:
|
||||
// - is_constructible_v<E, GF> is true; and
|
||||
// - is_assignable_v<E&, GF> is true; and
|
||||
// - is_nothrow_constructible_v<E, GF> || is_nothrow_move_constructible_v<T> ||
|
||||
// is_nothrow_move_constructible_v<E> is true.
|
||||
//
|
||||
// Effects:
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// has_val = false;
|
||||
// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
|
||||
// Returns: *this.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotMoveConstructible {
|
||||
NotMoveConstructible(NotMoveConstructible&&) = delete;
|
||||
NotMoveConstructible& operator=(NotMoveConstructible&&) = default;
|
||||
};
|
||||
|
||||
struct NotMoveAssignable {
|
||||
NotMoveAssignable(NotMoveAssignable&&) = default;
|
||||
NotMoveAssignable& operator=(NotMoveAssignable&&) = delete;
|
||||
};
|
||||
|
||||
struct MoveMayThrow {
|
||||
MoveMayThrow(MoveMayThrow const&) = default;
|
||||
MoveMayThrow& operator=(const MoveMayThrow&) = default;
|
||||
MoveMayThrow(MoveMayThrow&&) noexcept(false) {}
|
||||
MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; }
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_assignable_v<std::expected<int, int>&, std::unexpected<int>&&>);
|
||||
|
||||
// !is_constructible_v<E, GF>
|
||||
static_assert(
|
||||
!std::is_assignable_v<std::expected<int, NotMoveConstructible>&, std::unexpected<NotMoveConstructible>&&>);
|
||||
|
||||
// !is_assignable_v<E&, GF>
|
||||
static_assert(!std::is_assignable_v<std::expected<int, NotMoveAssignable>&, std::unexpected<NotMoveAssignable>&&>);
|
||||
|
||||
template <bool moveNoexcept, bool convertNoexcept>
|
||||
struct MaybeNoexcept {
|
||||
explicit MaybeNoexcept(int) noexcept(convertNoexcept);
|
||||
MaybeNoexcept(MaybeNoexcept&&) noexcept(moveNoexcept);
|
||||
MaybeNoexcept& operator=(MaybeNoexcept&&) = default;
|
||||
MaybeNoexcept& operator=(int);
|
||||
};
|
||||
|
||||
// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
|
||||
// is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<true, false>>&,
|
||||
std::unexpected<int>&&>);
|
||||
|
||||
// is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, true>>&,
|
||||
std::unexpected<int>&&>);
|
||||
|
||||
// !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_assignable_v<std::expected<MaybeNoexcept<true, true>, MaybeNoexcept<false, false>>&,
|
||||
std::unexpected<int>&&>);
|
||||
|
||||
// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<T> &&
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_assignable_v<std::expected<MaybeNoexcept<false, false>, MaybeNoexcept<false, false>>&,
|
||||
std::unexpected<int>&&>);
|
||||
|
||||
constexpr bool test() {
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// is_nothrow_constructible_v<E, GF>
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
{
|
||||
BothNoexcept::state oldState{};
|
||||
std::expected<BothNoexcept, BothNoexcept> e(std::in_place, oldState, 5);
|
||||
std::unexpected<int> un(10);
|
||||
decltype(auto) x = (e = std::move(un));
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothNoexcept>&>);
|
||||
assert(&x == &e);
|
||||
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e.error().movedFromInt);
|
||||
}
|
||||
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// !is_nothrow_constructible_v<E, GF> && is_nothrow_move_constructible_v<E>
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// T tmp(std::forward<Args>(args)...);
|
||||
// destroy_at(addressof(oldval));
|
||||
// construct_at(addressof(newval), std::move(tmp));
|
||||
{
|
||||
BothNoexcept::state oldState{};
|
||||
std::expected<BothNoexcept, MoveNoexceptConvThrow> e(std::in_place, oldState, 5);
|
||||
std::unexpected<int> un(10);
|
||||
decltype(auto) x = (e = std::move(un));
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, MoveNoexceptConvThrow>&>);
|
||||
assert(&x == &e);
|
||||
|
||||
assert(!oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(!e.error().movedFromInt);
|
||||
assert(e.error().movedFromTmp);
|
||||
}
|
||||
|
||||
// - If has_value() is true, equivalent to:
|
||||
// reinit-expected(unex, val, std::forward<GF>(e.error()));
|
||||
// !is_nothrow_constructible_v<E, GF> && !is_nothrow_move_constructible_v<E>
|
||||
// is_nothrow_move_constructible_v<T>
|
||||
//
|
||||
// In this case, it should call the branch
|
||||
// U tmp(std::move(oldval));
|
||||
// destroy_at(addressof(oldval));
|
||||
// try {
|
||||
// construct_at(addressof(newval), std::forward<Args>(args)...);
|
||||
// } catch (...) {
|
||||
// construct_at(addressof(oldval), std::move(tmp));
|
||||
// throw;
|
||||
// }
|
||||
{
|
||||
BothNoexcept::state oldState{};
|
||||
std::expected<BothNoexcept, BothMayThrow> e(std::in_place, oldState, 5);
|
||||
std::unexpected<int> un(10);
|
||||
decltype(auto) x = (e = std::move(un));
|
||||
static_assert(std::same_as<decltype(x), std::expected<BothNoexcept, BothMayThrow>&>);
|
||||
assert(&x == &e);
|
||||
|
||||
assert(oldState.moveCtorCalled);
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e.error().movedFromInt);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to: unex = std::forward<GF>(e.error());
|
||||
{
|
||||
Traced::state oldState{};
|
||||
Traced::state newState{};
|
||||
std::expected<int, Traced> e1(std::unexpect, oldState, 5);
|
||||
std::unexpected<Traced> e(std::in_place, newState, 10);
|
||||
decltype(auto) x = (e1 = std::move(e));
|
||||
static_assert(std::same_as<decltype(x), std::expected<int, Traced >&>);
|
||||
assert(&x == &e1);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
assert(oldState.moveAssignCalled);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
std::expected<int, ThrowOnConvert> e1(std::in_place, 5);
|
||||
std::unexpected<int> un(10);
|
||||
try {
|
||||
e1 = std::move(un);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
assert(*e1 == 5);
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class U, class... Args>
|
||||
// constexpr T& emplace(initializer_list<U> il, Args&&... args) noexcept;
|
||||
// Constraints: is_nothrow_constructible_v<T, initializer_list<U>&, Args...> is true.
|
||||
//
|
||||
// Effects: Equivalent to:
|
||||
// if (has_value()) {
|
||||
// destroy_at(addressof(val));
|
||||
// } else {
|
||||
// destroy_at(addressof(unex));
|
||||
// has_val = true;
|
||||
// }
|
||||
// return *construct_at(addressof(val), il, std::forward<Args>(args)...);
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class T, class... Args>
|
||||
concept CanEmplace = requires(T t, Args&&... args) { t.emplace(std::forward<Args>(args)...); };
|
||||
|
||||
static_assert(CanEmplace<std::expected<int, int>, int>);
|
||||
|
||||
template <bool Noexcept>
|
||||
struct CtorFromInitalizerList {
|
||||
CtorFromInitalizerList(std::initializer_list<int>&) noexcept(Noexcept);
|
||||
CtorFromInitalizerList(std::initializer_list<int>&, int) noexcept(Noexcept);
|
||||
};
|
||||
|
||||
static_assert(CanEmplace<std::expected<CtorFromInitalizerList<true>, int>, std::initializer_list<int>&>);
|
||||
static_assert(!CanEmplace<std::expected<CtorFromInitalizerList<false>, int>, std::initializer_list<int>&>);
|
||||
static_assert(CanEmplace<std::expected<CtorFromInitalizerList<true>, int>, std::initializer_list<int>&, int>);
|
||||
static_assert(!CanEmplace<std::expected<CtorFromInitalizerList<false>, int>, std::initializer_list<int>&, int>);
|
||||
|
||||
struct Data {
|
||||
std::initializer_list<int> il;
|
||||
int i;
|
||||
|
||||
constexpr Data(std::initializer_list<int>& l, int ii) noexcept : il(l), i(ii) {}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// has_value
|
||||
{
|
||||
auto list1 = {1, 2, 3};
|
||||
auto list2 = {4, 5, 6};
|
||||
std::expected<Data, int> e(std::in_place, list1, 5);
|
||||
decltype(auto) x = e.emplace(list2, 10);
|
||||
static_assert(std::same_as<decltype(x), Data&>);
|
||||
assert(&x == &(*e));
|
||||
|
||||
assert(e.has_value());
|
||||
assert(std::ranges::equal(e.value().il, list2));
|
||||
assert(e.value().i == 10);
|
||||
}
|
||||
|
||||
// !has_value
|
||||
{
|
||||
auto list = {4, 5, 6};
|
||||
std::expected<Data, int> e(std::unexpect, 5);
|
||||
decltype(auto) x = e.emplace(list, 10);
|
||||
static_assert(std::same_as<decltype(x), Data&>);
|
||||
assert(&x == &(*e));
|
||||
|
||||
assert(e.has_value());
|
||||
assert(std::ranges::equal(e.value().il, list));
|
||||
assert(e.value().i == 10);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// template<class... Args>
|
||||
// constexpr T& emplace(Args&&... args) noexcept;
|
||||
// Constraints: is_nothrow_constructible_v<T, Args...> is true.
|
||||
//
|
||||
// Effects: Equivalent to:
|
||||
// if (has_value()) {
|
||||
// destroy_at(addressof(val));
|
||||
// } else {
|
||||
// destroy_at(addressof(unex));
|
||||
// has_val = true;
|
||||
// }
|
||||
// return *construct_at(addressof(val), std::forward<Args>(args)...);
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class T, class... Args>
|
||||
concept CanEmplace = requires(T t, Args&&... args) { t.emplace(std::forward<Args>(args)...); };
|
||||
|
||||
static_assert(CanEmplace<std::expected<int, int>, int>);
|
||||
|
||||
template <bool Noexcept>
|
||||
struct CtorFromInt {
|
||||
CtorFromInt(int) noexcept(Noexcept);
|
||||
CtorFromInt(int, int) noexcept(Noexcept);
|
||||
};
|
||||
|
||||
static_assert(CanEmplace<std::expected<CtorFromInt<true>, int>, int>);
|
||||
static_assert(CanEmplace<std::expected<CtorFromInt<true>, int>, int, int>);
|
||||
static_assert(!CanEmplace<std::expected<CtorFromInt<false>, int>, int>);
|
||||
static_assert(!CanEmplace<std::expected<CtorFromInt<false>, int>, int, int>);
|
||||
|
||||
constexpr bool test() {
|
||||
// has_value
|
||||
{
|
||||
BothNoexcept::state oldState{};
|
||||
BothNoexcept::state newState{};
|
||||
std::expected<BothNoexcept, int> e(std::in_place, oldState, 5);
|
||||
decltype(auto) x = e.emplace(newState, 10);
|
||||
static_assert(std::same_as<decltype(x), BothNoexcept&>);
|
||||
assert(&x == &(*e));
|
||||
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e.has_value());
|
||||
assert(e.value().data_ == 10);
|
||||
}
|
||||
|
||||
// !has_value
|
||||
{
|
||||
BothMayThrow::state oldState{};
|
||||
std::expected<int, BothMayThrow> e(std::unexpect, oldState, 5);
|
||||
decltype(auto) x = e.emplace(10);
|
||||
static_assert(std::same_as<decltype(x), int&>);
|
||||
assert(&x == &(*e));
|
||||
|
||||
assert(oldState.dtorCalled);
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 10);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class U, class G>
|
||||
// constexpr explicit(see below) expected(const expected<U, G>&);
|
||||
//
|
||||
// Let:
|
||||
// - UF be const U&
|
||||
// - GF be const G&
|
||||
//
|
||||
// Constraints:
|
||||
// - is_constructible_v<T, UF> is true; and
|
||||
// - is_constructible_v<E, GF> is true; and
|
||||
// - is_constructible_v<T, expected<U, G>&> is false; and
|
||||
// - is_constructible_v<T, expected<U, G>> is false; and
|
||||
// - is_constructible_v<T, const expected<U, G>&> is false; and
|
||||
// - is_constructible_v<T, const expected<U, G>> is false; and
|
||||
// - is_convertible_v<expected<U, G>&, T> is false; and
|
||||
// - is_convertible_v<expected<U, G>&&, T> is false; and
|
||||
// - is_convertible_v<const expected<U, G>&, T> is false; and
|
||||
// - is_convertible_v<const expected<U, G>&&, T> is false; and
|
||||
// - is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
|
||||
// - is_constructible_v<unexpected<E>, expected<U, G>> is false; and
|
||||
// - is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
|
||||
// - is_constructible_v<unexpected<E>, const expected<U, G>> is false.
|
||||
//
|
||||
// Effects: If rhs.has_value(), direct-non-list-initializes val with std::forward<UF>(*rhs). Otherwise, direct-non-list-initializes unex with std::forward<GF>(rhs.error()).
|
||||
//
|
||||
// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val or unex.
|
||||
//
|
||||
// Remarks: The expression inside explicit is equivalent to !is_convertible_v<UF, T> || !is_convertible_v<GF, E>.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
template <class T1, class Err1, class T2, class Err2>
|
||||
concept canCstrFromExpected = std::is_constructible_v<std::expected<T1, Err1>, const std::expected<T2, Err2>&>;
|
||||
|
||||
struct CtorFromInt {
|
||||
CtorFromInt(int);
|
||||
};
|
||||
|
||||
static_assert(canCstrFromExpected<CtorFromInt, int, int, int>);
|
||||
|
||||
struct NoCtorFromInt {};
|
||||
|
||||
// !is_constructible_v<T, UF>
|
||||
static_assert(!canCstrFromExpected<NoCtorFromInt, int, int, int>);
|
||||
|
||||
// !is_constructible_v<E, GF>
|
||||
static_assert(!canCstrFromExpected<int, NoCtorFromInt, int, int>);
|
||||
|
||||
template <class T>
|
||||
struct CtorFrom {
|
||||
explicit CtorFrom(int)
|
||||
requires(!std::same_as<T, int>);
|
||||
explicit CtorFrom(T);
|
||||
explicit CtorFrom(auto&&) = delete;
|
||||
};
|
||||
|
||||
// is_constructible_v<T, expected<U, G>&>
|
||||
static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int>&>, int, int, int>);
|
||||
|
||||
// is_constructible_v<T, expected<U, G>>
|
||||
static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int>&&>, int, int, int>);
|
||||
|
||||
// is_constructible_v<T, expected<U, G>&>
|
||||
// note that this is true because it is covered by the other overload
|
||||
// template<class U = T> constexpr explicit(see below) expected(U&& v);
|
||||
// The fact that it is not ambiguous proves that the overload under testing is removed
|
||||
static_assert(canCstrFromExpected<CtorFrom<std::expected<int, int> const&>, int, int, int>);
|
||||
|
||||
// is_constructible_v<T, expected<U, G>>
|
||||
static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int> const&&>, int, int, int>);
|
||||
|
||||
template <class T>
|
||||
struct ConvertFrom {
|
||||
ConvertFrom(int)
|
||||
requires(!std::same_as<T, int>);
|
||||
ConvertFrom(T);
|
||||
ConvertFrom(auto&&) = delete;
|
||||
};
|
||||
|
||||
// is_convertible_v<expected<U, G>&, T>
|
||||
static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int>&>, int, int, int>);
|
||||
|
||||
// is_convertible_v<expected<U, G>&&, T>
|
||||
static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int>&&>, int, int, int>);
|
||||
|
||||
// is_convertible_v<const expected<U, G>&, T>
|
||||
// note that this is true because it is covered by the other overload
|
||||
// template<class U = T> constexpr explicit(see below) expected(U&& v);
|
||||
// The fact that it is not ambiguous proves that the overload under testing is removed
|
||||
static_assert(canCstrFromExpected<ConvertFrom<std::expected<int, int> const&>, int, int, int>);
|
||||
|
||||
// is_convertible_v<const expected<U, G>&&, T>
|
||||
static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int> const&&>, int, int, int>);
|
||||
|
||||
// Note for below 4 tests, because their E is constructible from cvref of std::expected<int, int>,
|
||||
// unexpected<E> will be constructible from cvref of std::expected<int, int>
|
||||
// is_constructible_v<unexpected<E>, expected<U, G>&>
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&>, int, int>);
|
||||
|
||||
// is_constructible_v<unexpected<E>, expected<U, G>>
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&&>, int, int>);
|
||||
|
||||
// is_constructible_v<unexpected<E>, const expected<U, G>&> is false
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&>, int, int>);
|
||||
|
||||
// is_constructible_v<unexpected<E>, const expected<U, G>>
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&&>, int, int>);
|
||||
|
||||
// test explicit
|
||||
static_assert(std::is_convertible_v<const std::expected<int, int>&, std::expected<short, long>>);
|
||||
|
||||
// !is_convertible_v<UF, T>
|
||||
static_assert(std::is_constructible_v<std::expected<CtorFrom<int>, int>, const std::expected<int, int>&>);
|
||||
static_assert(!std::is_convertible_v<const std::expected<int, int>&, std::expected<CtorFrom<int>, int>>);
|
||||
|
||||
// !is_convertible_v<GF, E>.
|
||||
static_assert(std::is_constructible_v<std::expected<int, CtorFrom<int>>, const std::expected<int, int>&>);
|
||||
static_assert(!std::is_convertible_v<const std::expected<int, int>&, std::expected<int, CtorFrom<int>>>);
|
||||
|
||||
struct Data {
|
||||
int i;
|
||||
constexpr Data(int ii) : i(ii) {}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// convert the value
|
||||
{
|
||||
const std::expected<int, int> e1(5);
|
||||
std::expected<Data, int> e2 = e1;
|
||||
assert(e2.has_value());
|
||||
assert(e2.value().i == 5);
|
||||
assert(e1.has_value());
|
||||
assert(e1.value() == 5);
|
||||
}
|
||||
|
||||
// convert the error
|
||||
{
|
||||
const std::expected<int, int> e1(std::unexpect, 5);
|
||||
std::expected<int, Data> e2 = e1;
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().i == 5);
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error() == 5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct ThrowingInt {
|
||||
ThrowingInt(int) { throw Except{}; }
|
||||
};
|
||||
|
||||
// throw on converting value
|
||||
{
|
||||
const std::expected<int, int> e1;
|
||||
try {
|
||||
[[maybe_unused]] std::expected<ThrowingInt, int> e2 = e1;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
// throw on converting error
|
||||
{
|
||||
const std::expected<int, int> e1(std::unexpect);
|
||||
try {
|
||||
[[maybe_unused]] std::expected<int, ThrowingInt> e2 = e1;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class U, class G>
|
||||
// constexpr explicit(see below) expected(expected<U, G>&&);
|
||||
//
|
||||
// Let:
|
||||
// - UF be const U
|
||||
// - GF be const G
|
||||
//
|
||||
// Constraints:
|
||||
// - is_constructible_v<T, UF> is true; and
|
||||
// - is_constructible_v<E, GF> is true; and
|
||||
// - is_constructible_v<T, expected<U, G>&> is false; and
|
||||
// - is_constructible_v<T, expected<U, G>> is false; and
|
||||
// - is_constructible_v<T, const expected<U, G>&> is false; and
|
||||
// - is_constructible_v<T, const expected<U, G>> is false; and
|
||||
// - is_convertible_v<expected<U, G>&, T> is false; and
|
||||
// - is_convertible_v<expected<U, G>&&, T> is false; and
|
||||
// - is_convertible_v<const expected<U, G>&, T> is false; and
|
||||
// - is_convertible_v<const expected<U, G>&&, T> is false; and
|
||||
// - is_constructible_v<unexpected<E>, expected<U, G>&> is false; and
|
||||
// - is_constructible_v<unexpected<E>, expected<U, G>> is false; and
|
||||
// - is_constructible_v<unexpected<E>, const expected<U, G>&> is false; and
|
||||
// - is_constructible_v<unexpected<E>, const expected<U, G>> is false.
|
||||
//
|
||||
// Effects: If rhs.has_value(), direct-non-list-initializes val with std::forward<UF>(*rhs). Otherwise, direct-non-list-initializes unex with std::forward<GF>(rhs.error()).
|
||||
//
|
||||
// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val or unex.
|
||||
//
|
||||
// Remarks: The expression inside explicit is equivalent to !is_convertible_v<UF, T> || !is_convertible_v<GF, E>.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
template <class T1, class Err1, class T2, class Err2>
|
||||
concept canCstrFromExpected = std::is_constructible_v<std::expected<T1, Err1>, std::expected<T2, Err2>&&>;
|
||||
|
||||
struct CtorFromInt {
|
||||
CtorFromInt(int);
|
||||
};
|
||||
|
||||
static_assert(canCstrFromExpected<CtorFromInt, int, int, int>);
|
||||
|
||||
struct NoCtorFromInt {};
|
||||
|
||||
// !is_constructible_v<T, UF>
|
||||
static_assert(!canCstrFromExpected<NoCtorFromInt, int, int, int>);
|
||||
|
||||
// !is_constructible_v<E, GF>
|
||||
static_assert(!canCstrFromExpected<int, NoCtorFromInt, int, int>);
|
||||
|
||||
template <class T>
|
||||
struct CtorFrom {
|
||||
explicit CtorFrom(int)
|
||||
requires(!std::same_as<T, int>);
|
||||
explicit CtorFrom(T);
|
||||
explicit CtorFrom(auto&&) = delete;
|
||||
};
|
||||
|
||||
// is_constructible_v<T, expected<U, G>&>
|
||||
static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int>&>, int, int, int>);
|
||||
|
||||
// is_constructible_v<T, expected<U, G>>
|
||||
// note that this is true because it is covered by the other overload
|
||||
// template<class U = T> constexpr explicit(see below) expected(U&& v);
|
||||
// The fact that it is not ambiguous proves that the overload under testing is removed
|
||||
static_assert(canCstrFromExpected<CtorFrom<std::expected<int, int>&&>, int, int, int>);
|
||||
|
||||
// is_constructible_v<T, expected<U, G>&>
|
||||
static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int> const&>, int, int, int>);
|
||||
|
||||
// is_constructible_v<T, expected<U, G>>
|
||||
static_assert(!canCstrFromExpected<CtorFrom<std::expected<int, int> const&&>, int, int, int>);
|
||||
|
||||
template <class T>
|
||||
struct ConvertFrom {
|
||||
ConvertFrom(int)
|
||||
requires(!std::same_as<T, int>);
|
||||
ConvertFrom(T);
|
||||
ConvertFrom(auto&&) = delete;
|
||||
};
|
||||
|
||||
// is_convertible_v<expected<U, G>&, T>
|
||||
static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int>&>, int, int, int>);
|
||||
|
||||
// is_convertible_v<expected<U, G>&&, T>
|
||||
// note that this is true because it is covered by the other overload
|
||||
// template<class U = T> constexpr explicit(see below) expected(U&& v);
|
||||
// The fact that it is not ambiguous proves that the overload under testing is removed
|
||||
static_assert(canCstrFromExpected<ConvertFrom<std::expected<int, int>&&>, int, int, int>);
|
||||
|
||||
// is_convertible_v<const expected<U, G>&, T>
|
||||
static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int> const&>, int, int, int>);
|
||||
|
||||
// is_convertible_v<const expected<U, G>&&, T>
|
||||
static_assert(!canCstrFromExpected<ConvertFrom<std::expected<int, int> const&&>, int, int, int>);
|
||||
|
||||
// is_constructible_v<unexpected<E>, expected<U, G>&>
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&>, int, int>);
|
||||
|
||||
// is_constructible_v<unexpected<E>, expected<U, G>>
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int>&&>, int, int>);
|
||||
|
||||
// is_constructible_v<unexpected<E>, const expected<U, G>&> is false
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&>, int, int>);
|
||||
|
||||
// is_constructible_v<unexpected<E>, const expected<U, G>>
|
||||
static_assert(!canCstrFromExpected<int, CtorFrom<std::expected<int, int> const&&>, int, int>);
|
||||
|
||||
// test explicit
|
||||
static_assert(std::is_convertible_v<std::expected<int, int>&&, std::expected<short, long>>);
|
||||
|
||||
// !is_convertible_v<UF, T>
|
||||
static_assert(std::is_constructible_v<std::expected<CtorFrom<int>, int>, std::expected<int, int>&&>);
|
||||
static_assert(!std::is_convertible_v<std::expected<int, int>&&, std::expected<CtorFrom<int>, int>>);
|
||||
|
||||
// !is_convertible_v<GF, E>.
|
||||
static_assert(std::is_constructible_v<std::expected<int, CtorFrom<int>>, std::expected<int, int>&&>);
|
||||
static_assert(!std::is_convertible_v<std::expected<int, int>&&, std::expected<int, CtorFrom<int>>>);
|
||||
|
||||
struct Data {
|
||||
MoveOnly data;
|
||||
constexpr Data(MoveOnly&& m) : data(std::move(m)) {}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// convert the value
|
||||
{
|
||||
std::expected<MoveOnly, int> e1(5);
|
||||
std::expected<Data, int> e2 = std::move(e1);
|
||||
assert(e2.has_value());
|
||||
assert(e2.value().data.get() == 5);
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().get() == 0);
|
||||
}
|
||||
|
||||
// convert the error
|
||||
{
|
||||
std::expected<int, MoveOnly> e1(std::unexpect, 5);
|
||||
std::expected<int, Data> e2 = std::move(e1);
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().data.get() == 5);
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().get() == 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct ThrowingInt {
|
||||
ThrowingInt(int) { throw Except{}; }
|
||||
};
|
||||
|
||||
// throw on converting value
|
||||
{
|
||||
const std::expected<int, int> e1;
|
||||
try {
|
||||
[[maybe_unused]] std::expected<ThrowingInt, int> e2 = e1;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
// throw on converting error
|
||||
{
|
||||
const std::expected<int, int> e1(std::unexpect);
|
||||
try {
|
||||
[[maybe_unused]] std::expected<int, ThrowingInt> e2 = e1;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr expected(const expected& rhs);
|
||||
//
|
||||
// Effects: If rhs.has_value() is true, direct-non-list-initializes val with *rhs.
|
||||
// Otherwise, direct-non-list-initializes unex with rhs.error().
|
||||
//
|
||||
// Postconditions: rhs.has_value() == this->has_value().
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val or unex.
|
||||
//
|
||||
// Remarks: This constructor is defined as deleted unless
|
||||
// - is_copy_constructible_v<T> is true and
|
||||
// - is_copy_constructible_v<E> is true.
|
||||
//
|
||||
// This constructor is trivial if
|
||||
// - is_trivially_copy_constructible_v<T> is true and
|
||||
// - is_trivially_copy_constructible_v<E> is true.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NonCopyable {
|
||||
NonCopyable(const NonCopyable&) = delete;
|
||||
};
|
||||
|
||||
struct CopyableNonTrivial {
|
||||
int i;
|
||||
constexpr CopyableNonTrivial(int ii) : i(ii) {}
|
||||
constexpr CopyableNonTrivial(const CopyableNonTrivial& o) { i = o.i; }
|
||||
friend constexpr bool operator==(const CopyableNonTrivial&, const CopyableNonTrivial&) = default;
|
||||
};
|
||||
|
||||
// Test: This constructor is defined as deleted unless
|
||||
// - is_copy_constructible_v<T> is true and
|
||||
// - is_copy_constructible_v<E> is true.
|
||||
static_assert(std::is_copy_constructible_v<std::expected<int, int>>);
|
||||
static_assert(std::is_copy_constructible_v<std::expected<CopyableNonTrivial, int>>);
|
||||
static_assert(std::is_copy_constructible_v<std::expected<int, CopyableNonTrivial>>);
|
||||
static_assert(std::is_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>);
|
||||
static_assert(!std::is_copy_constructible_v<std::expected<NonCopyable, int>>);
|
||||
static_assert(!std::is_copy_constructible_v<std::expected<int, NonCopyable>>);
|
||||
static_assert(!std::is_copy_constructible_v<std::expected<NonCopyable, NonCopyable>>);
|
||||
|
||||
// Test: This constructor is trivial if
|
||||
// - is_trivially_copy_constructible_v<T> is true and
|
||||
// - is_trivially_copy_constructible_v<E> is true.
|
||||
#if __cpp_concepts >= 202002
|
||||
static_assert(std::is_trivially_copy_constructible_v<std::expected<int, int>>);
|
||||
#endif
|
||||
static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, int>>);
|
||||
static_assert(!std::is_trivially_copy_constructible_v<std::expected<int, CopyableNonTrivial>>);
|
||||
static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// copy the value non-trivial
|
||||
{
|
||||
const std::expected<CopyableNonTrivial, int> e1(5);
|
||||
auto e2 = e1;
|
||||
assert(e2.has_value());
|
||||
assert(e2.value().i == 5);
|
||||
}
|
||||
|
||||
// copy the error non-trivial
|
||||
{
|
||||
const std::expected<int, CopyableNonTrivial> e1(std::unexpect, 5);
|
||||
auto e2 = e1;
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().i == 5);
|
||||
}
|
||||
|
||||
// copy the value trivial
|
||||
{
|
||||
const std::expected<int, int> e1(5);
|
||||
auto e2 = e1;
|
||||
assert(e2.has_value());
|
||||
assert(e2.value() == 5);
|
||||
}
|
||||
|
||||
// copy the error trivial
|
||||
{
|
||||
const std::expected<int, int> e1(std::unexpect, 5);
|
||||
auto e2 = e1;
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error() == 5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing() = default;
|
||||
Throwing(const Throwing&) { throw Except{}; }
|
||||
};
|
||||
|
||||
// throw on copying value
|
||||
{
|
||||
const std::expected<Throwing, int> e1;
|
||||
try {
|
||||
[[maybe_unused]] auto e2 = e1;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
// throw on copying error
|
||||
{
|
||||
const std::expected<int, Throwing> e1(std::unexpect);
|
||||
try {
|
||||
[[maybe_unused]] auto e2 = e1;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
//
|
||||
// constexpr expected();
|
||||
|
||||
// Constraints: is_default_constructible_v<T> is true.
|
||||
//
|
||||
// Effects: Value-initializes val.
|
||||
// Postconditions: has_value() is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NoDedefaultCtor {
|
||||
NoDedefaultCtor() = delete;
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_default_constructible_v<std::expected<int, int>>);
|
||||
static_assert(!std::is_default_constructible_v<std::expected<NoDedefaultCtor, int>>);
|
||||
|
||||
struct MyInt {
|
||||
int i;
|
||||
friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
|
||||
};
|
||||
|
||||
template <class T, class E>
|
||||
constexpr void testDefaultCtor() {
|
||||
std::expected<T, E> e;
|
||||
assert(e.has_value());
|
||||
assert(e.value() == T());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void testTypes() {
|
||||
testDefaultCtor<T, int>();
|
||||
testDefaultCtor<T, NoDedefaultCtor>();
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
testTypes<int>();
|
||||
testTypes<MyInt>();
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing() { throw Except{}; };
|
||||
};
|
||||
|
||||
try {
|
||||
std::expected<Throwing, int> u;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class... Args>
|
||||
// constexpr explicit expected(in_place_t, Args&&... args);
|
||||
//
|
||||
// Constraints: is_constructible_v<T, Args...> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes val with std::forward<Args>(args)....
|
||||
//
|
||||
// Postconditions: has_value() is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, std::in_place_t>);
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, std::in_place_t, int>);
|
||||
|
||||
// !is_constructible_v<T, Args...>
|
||||
struct foo {};
|
||||
static_assert(!std::is_constructible_v<std::expected<foo, int>, std::in_place_t, int>);
|
||||
|
||||
// test explicit
|
||||
template <class T>
|
||||
void conversion_test(T);
|
||||
|
||||
template <class T, class... Args>
|
||||
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
|
||||
static_assert(ImplicitlyConstructible<int, int>);
|
||||
|
||||
static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::in_place_t>);
|
||||
static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::in_place_t, int>);
|
||||
|
||||
struct CopyOnly {
|
||||
int i;
|
||||
constexpr CopyOnly(int ii) : i(ii) {}
|
||||
CopyOnly(const CopyOnly&) = default;
|
||||
CopyOnly(CopyOnly&&) = delete;
|
||||
friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr void testInt() {
|
||||
std::expected<T, int> e(std::in_place, 5);
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 5);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void testLValue() {
|
||||
T t(5);
|
||||
std::expected<T, int> e(std::in_place, t);
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 5);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void testRValue() {
|
||||
std::expected<T, int> e(std::in_place, T(5));
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 5);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
testInt<int>();
|
||||
testInt<CopyOnly>();
|
||||
testInt<MoveOnly>();
|
||||
testLValue<int>();
|
||||
testLValue<CopyOnly>();
|
||||
testRValue<int>();
|
||||
testRValue<MoveOnly>();
|
||||
|
||||
// no arg
|
||||
{
|
||||
std::expected<int, int> e(std::in_place);
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 0);
|
||||
}
|
||||
|
||||
// one arg
|
||||
{
|
||||
std::expected<int, int> e(std::in_place, 5);
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 5);
|
||||
}
|
||||
|
||||
// multi args
|
||||
{
|
||||
std::expected<std::tuple<int, short, MoveOnly>, int> e(std::in_place, 1, 2, MoveOnly(3));
|
||||
assert(e.has_value());
|
||||
assert((e.value() == std::tuple<int, short, MoveOnly>(1, 2, MoveOnly(3))));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(int) { throw Except{}; };
|
||||
};
|
||||
|
||||
try {
|
||||
std::expected<Throwing, int> u(std::in_place, 5);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// template<class U, class... Args>
|
||||
// constexpr explicit expected(in_place_t, initializer_list<U> il, Args&&... args);
|
||||
//
|
||||
// Constraints: is_constructible_v<T, initializer_list<U>&, Args...> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes val with il, std::forward<Args>(args)....
|
||||
//
|
||||
// Postconditions: has_value() is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(
|
||||
std::is_constructible_v<std::expected<std::vector<int>, int>, std::in_place_t, std::initializer_list<int>>);
|
||||
|
||||
// !is_constructible_v<T, initializer_list<U>&, Args...>
|
||||
static_assert(!std::is_constructible_v<std::expected<int, int>, std::in_place_t, std::initializer_list<int>>);
|
||||
|
||||
// test explicit
|
||||
template <class T>
|
||||
void conversion_test(T);
|
||||
|
||||
template <class T, class... Args>
|
||||
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
|
||||
static_assert(ImplicitlyConstructible<int, int>);
|
||||
|
||||
static_assert(
|
||||
!ImplicitlyConstructible<std::expected<std::vector<int>, int>, std::in_place_t, std::initializer_list<int>>);
|
||||
|
||||
template <class... Ts>
|
||||
struct Data {
|
||||
std::vector<int> vec_;
|
||||
std::tuple<Ts...> tuple_;
|
||||
|
||||
template <class... Us>
|
||||
requires std::is_constructible_v<std::tuple<Ts...>, Us&&...>
|
||||
constexpr Data(std::initializer_list<int> il, Us&&... us) : vec_(il), tuple_(std::forward<Us>(us)...) {}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// no arg
|
||||
{
|
||||
std::expected<Data<>, int> e(std::in_place, {1, 2, 3});
|
||||
assert(e.has_value());
|
||||
auto expectedList = {1, 2, 3};
|
||||
assert(std::ranges::equal(e.value().vec_, expectedList));
|
||||
}
|
||||
|
||||
// one arg
|
||||
{
|
||||
std::expected<Data<MoveOnly>, int> e(std::in_place, {4, 5, 6}, MoveOnly(5));
|
||||
assert(e.has_value());
|
||||
auto expectedList = {4, 5, 6};
|
||||
assert((std::ranges::equal(e.value().vec_, expectedList)));
|
||||
assert(std::get<0>(e.value().tuple_) == 5);
|
||||
}
|
||||
|
||||
// multi args
|
||||
{
|
||||
int i = 5;
|
||||
int j = 6;
|
||||
MoveOnly m(7);
|
||||
std::expected<Data<int&, int&&, MoveOnly>, int> e(std::in_place, {1, 2}, i, std::move(j), std::move(m));
|
||||
assert(e.has_value());
|
||||
auto expectedList = {1, 2};
|
||||
assert((std::ranges::equal(e.value().vec_, expectedList)));
|
||||
assert(&std::get<0>(e.value().tuple_) == &i);
|
||||
assert(&std::get<1>(e.value().tuple_) == &j);
|
||||
assert(std::get<2>(e.value().tuple_) == 7);
|
||||
assert(m.get() == 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(std::initializer_list<int>, int) { throw Except{}; };
|
||||
};
|
||||
|
||||
try {
|
||||
std::expected<Throwing, int> u(std::in_place, {1, 2}, 5);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr expected(expected&& rhs) noexcept(see below);
|
||||
//
|
||||
// Constraints:
|
||||
// - is_move_constructible_v<T> is true and
|
||||
// - is_move_constructible_v<E> is true.
|
||||
//
|
||||
// Effects: If rhs.has_value() is true, direct-non-list-initializes val with std::move(*rhs).
|
||||
// Otherwise, direct-non-list-initializes unex with std::move(rhs.error()).
|
||||
//
|
||||
// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val or unex.
|
||||
//
|
||||
// Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>.
|
||||
//
|
||||
// This constructor is trivial if
|
||||
// - is_trivially_move_constructible_v<T> is true and
|
||||
// - is_trivially_move_constructible_v<E> is true.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NonMovable {
|
||||
NonMovable(NonMovable&&) = delete;
|
||||
};
|
||||
|
||||
struct MovableNonTrivial {
|
||||
int i;
|
||||
constexpr MovableNonTrivial(int ii) : i(ii) {}
|
||||
constexpr MovableNonTrivial(MovableNonTrivial&& o) : i(o.i) { o.i = 0; }
|
||||
friend constexpr bool operator==(const MovableNonTrivial&, const MovableNonTrivial&) = default;
|
||||
};
|
||||
|
||||
struct MoveMayThrow {
|
||||
MoveMayThrow(MoveMayThrow&&) {}
|
||||
};
|
||||
|
||||
// Test Constraints:
|
||||
// - is_move_constructible_v<T> is true and
|
||||
// - is_move_constructible_v<E> is true.
|
||||
static_assert(std::is_move_constructible_v<std::expected<int, int>>);
|
||||
static_assert(std::is_move_constructible_v<std::expected<MovableNonTrivial, int>>);
|
||||
static_assert(std::is_move_constructible_v<std::expected<int, MovableNonTrivial>>);
|
||||
static_assert(std::is_move_constructible_v<std::expected<MovableNonTrivial, MovableNonTrivial>>);
|
||||
static_assert(!std::is_move_constructible_v<std::expected<NonMovable, int>>);
|
||||
static_assert(!std::is_move_constructible_v<std::expected<int, NonMovable>>);
|
||||
static_assert(!std::is_move_constructible_v<std::expected<NonMovable, NonMovable>>);
|
||||
|
||||
// Test: This constructor is trivial if
|
||||
// - is_trivially_move_constructible_v<T> is true and
|
||||
// - is_trivially_move_constructible_v<E> is true.
|
||||
#if __cpp_concepts >= 202002
|
||||
static_assert(std::is_trivially_move_constructible_v<std::expected<int, int>>);
|
||||
#endif
|
||||
static_assert(!std::is_trivially_move_constructible_v<std::expected<MovableNonTrivial, int>>);
|
||||
static_assert(!std::is_trivially_move_constructible_v<std::expected<int, MovableNonTrivial>>);
|
||||
static_assert(!std::is_trivially_move_constructible_v<std::expected<MovableNonTrivial, MovableNonTrivial>>);
|
||||
|
||||
// Test: The exception specification is equivalent to
|
||||
// is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>.
|
||||
static_assert(std::is_nothrow_move_constructible_v<std::expected<int, int>>);
|
||||
static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, int>>);
|
||||
static_assert(!std::is_nothrow_move_constructible_v<std::expected<int, MoveMayThrow>>);
|
||||
static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, MoveMayThrow>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// move the value non-trivial
|
||||
{
|
||||
std::expected<MovableNonTrivial, int> e1(5);
|
||||
auto e2 = std::move(e1);
|
||||
assert(e2.has_value());
|
||||
assert(e2.value().i == 5);
|
||||
assert(e1.has_value());
|
||||
assert(e1.value().i == 0);
|
||||
}
|
||||
|
||||
// move the error non-trivial
|
||||
{
|
||||
std::expected<int, MovableNonTrivial> e1(std::unexpect, 5);
|
||||
auto e2 = std::move(e1);
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().i == 5);
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().i == 0);
|
||||
}
|
||||
|
||||
// move the value trivial
|
||||
{
|
||||
std::expected<int, int> e1(5);
|
||||
auto e2 = std::move(e1);
|
||||
assert(e2.has_value());
|
||||
assert(e2.value() == 5);
|
||||
assert(e1.has_value());
|
||||
}
|
||||
|
||||
// move the error trivial
|
||||
{
|
||||
std::expected<int, int> e1(std::unexpect, 5);
|
||||
auto e2 = std::move(e1);
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error() == 5);
|
||||
assert(!e1.has_value());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing() = default;
|
||||
Throwing(Throwing&&) { throw Except{}; }
|
||||
};
|
||||
|
||||
// throw on moving value
|
||||
{
|
||||
std::expected<Throwing, int> e1;
|
||||
try {
|
||||
[[maybe_unused]] auto e2 = std::move(e1);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
// throw on moving error
|
||||
{
|
||||
std::expected<int, Throwing> e1(std::unexpect);
|
||||
try {
|
||||
[[maybe_unused]] auto e2 = std::move(e1);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class U = T>
|
||||
// constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);
|
||||
//
|
||||
// Constraints:
|
||||
// - is_same_v<remove_cvref_t<U>, in_place_t> is false; and
|
||||
// - is_same_v<expected, remove_cvref_t<U>> is false; and
|
||||
// - remove_cvref_t<U> is not a specialization of unexpected; and
|
||||
// - is_constructible_v<T, U> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes val with std::forward<U>(v).
|
||||
//
|
||||
// Postconditions: has_value() is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of val.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, int>);
|
||||
|
||||
// is_same_v<remove_cvref_t<U>, in_place_t>
|
||||
struct FromJustInplace {
|
||||
FromJustInplace(std::in_place_t);
|
||||
};
|
||||
static_assert(!std::is_constructible_v<std::expected<FromJustInplace, int>, std::in_place_t>);
|
||||
static_assert(!std::is_constructible_v<std::expected<FromJustInplace, int>, std::in_place_t const&>);
|
||||
|
||||
// is_same_v<expected, remove_cvref_t<U>>
|
||||
// Note that result is true because it is covered by the constructors that take expected
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, std::expected<int, int>&>);
|
||||
|
||||
// remove_cvref_t<U> is a specialization of unexpected
|
||||
// Note that result is true because it is covered by the constructors that take unexpected
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpected<int>&>);
|
||||
|
||||
// !is_constructible_v<T, U>
|
||||
struct foo {};
|
||||
static_assert(!std::is_constructible_v<std::expected<int, int>, foo>);
|
||||
|
||||
// test explicit(!is_convertible_v<U, T>)
|
||||
struct NotConvertible {
|
||||
explicit NotConvertible(int);
|
||||
};
|
||||
static_assert(std::is_convertible_v<int, std::expected<int, int>>);
|
||||
static_assert(!std::is_convertible_v<int, std::expected<NotConvertible, int>>);
|
||||
|
||||
struct CopyOnly {
|
||||
int i;
|
||||
constexpr CopyOnly(int ii) : i(ii) {}
|
||||
CopyOnly(const CopyOnly&) = default;
|
||||
CopyOnly(CopyOnly&&) = delete;
|
||||
friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr void testInt() {
|
||||
std::expected<T, int> e(5);
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 5);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void testLValue() {
|
||||
T t(5);
|
||||
std::expected<T, int> e(t);
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 5);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void testRValue() {
|
||||
std::expected<T, int> e(T(5));
|
||||
assert(e.has_value());
|
||||
assert(e.value() == 5);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
testInt<int>();
|
||||
testInt<CopyOnly>();
|
||||
testInt<MoveOnly>();
|
||||
testLValue<int>();
|
||||
testLValue<CopyOnly>();
|
||||
testRValue<int>();
|
||||
testRValue<MoveOnly>();
|
||||
|
||||
// Test default template argument.
|
||||
// Without it, the template parameter cannot be deduced from an initializer list
|
||||
{
|
||||
struct Bar {
|
||||
int i;
|
||||
int j;
|
||||
constexpr Bar(int ii, int jj) : i(ii), j(jj) {}
|
||||
};
|
||||
|
||||
std::expected<Bar, int> e({5, 6});
|
||||
assert(e.value().i == 5);
|
||||
assert(e.value().j == 6);
|
||||
}
|
||||
|
||||
// this is a confusing example, but the behaviour
|
||||
// is exactly what is specified in the spec
|
||||
// see https://cplusplus.github.io/LWG/issue3836
|
||||
{
|
||||
struct BaseError {};
|
||||
struct DerivedError : BaseError {};
|
||||
|
||||
std::expected<bool, DerivedError> e1(false);
|
||||
std::expected<bool, BaseError> e2(e1);
|
||||
assert(e2.has_value());
|
||||
assert(e2.value()); // yes, e2 holds "true"
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(int) { throw Except{}; };
|
||||
};
|
||||
|
||||
try {
|
||||
std::expected<Throwing, int> u(5);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class... Args>
|
||||
// constexpr explicit expected(unexpect_t, Args&&... args);
|
||||
//
|
||||
// Constraints: is_constructible_v<E, Args...> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....
|
||||
//
|
||||
// Postconditions: has_value() is false.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of unex.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpect_t>);
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpect_t, int>);
|
||||
|
||||
// !is_constructible_v<T, Args...>
|
||||
struct foo {};
|
||||
static_assert(!std::is_constructible_v<std::expected<int, foo>, std::unexpect_t, int>);
|
||||
|
||||
// test explicit
|
||||
template <class T>
|
||||
void conversion_test(T);
|
||||
|
||||
template <class T, class... Args>
|
||||
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
|
||||
static_assert(ImplicitlyConstructible<int, int>);
|
||||
|
||||
static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::unexpect_t>);
|
||||
static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::unexpect_t, int>);
|
||||
|
||||
struct CopyOnly {
|
||||
int i;
|
||||
constexpr CopyOnly(int ii) : i(ii) {}
|
||||
CopyOnly(const CopyOnly&) = default;
|
||||
CopyOnly(CopyOnly&&) = delete;
|
||||
friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr void testInt() {
|
||||
std::expected<int, T> e(std::unexpect, 5);
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 5);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void testLValue() {
|
||||
T t(5);
|
||||
std::expected<int, T> e(std::unexpect, t);
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 5);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void testRValue() {
|
||||
std::expected<int, T> e(std::unexpect, T(5));
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 5);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
testInt<int>();
|
||||
testInt<CopyOnly>();
|
||||
testInt<MoveOnly>();
|
||||
testLValue<int>();
|
||||
testLValue<CopyOnly>();
|
||||
testRValue<int>();
|
||||
testRValue<MoveOnly>();
|
||||
|
||||
// no arg
|
||||
{
|
||||
std::expected<int, int> e(std::unexpect);
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 0);
|
||||
}
|
||||
|
||||
// one arg
|
||||
{
|
||||
std::expected<int, int> e(std::unexpect, 5);
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 5);
|
||||
}
|
||||
|
||||
// multi args
|
||||
{
|
||||
std::expected<int, std::tuple<int, short, MoveOnly>> e(std::unexpect, 1, 2, MoveOnly(3));
|
||||
assert(!e.has_value());
|
||||
assert((e.error() == std::tuple<int, short, MoveOnly>(1, 2, MoveOnly(3))));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(int) { throw Except{}; };
|
||||
};
|
||||
|
||||
try {
|
||||
std::expected<int, Throwing> u(std::unexpect, 5);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// template<class U, class... Args>
|
||||
// constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
|
||||
//
|
||||
// Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes unex with il, std::forward<Args>(args)....
|
||||
//
|
||||
// Postconditions: has_value() is false.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of unex.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(
|
||||
std::is_constructible_v<std::expected<int, std::vector<int>>, std::unexpect_t, std::initializer_list<int>>);
|
||||
|
||||
// !is_constructible_v<T, initializer_list<U>&, Args...>
|
||||
static_assert(!std::is_constructible_v<std::expected<int, int>, std::unexpect_t, std::initializer_list<int>>);
|
||||
|
||||
// test explicit
|
||||
template <class T>
|
||||
void conversion_test(T);
|
||||
|
||||
template <class T, class... Args>
|
||||
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
|
||||
static_assert(ImplicitlyConstructible<int, int>);
|
||||
|
||||
static_assert(
|
||||
!ImplicitlyConstructible<std::expected<int, std::vector<int>>, std::unexpect_t, std::initializer_list<int>>);
|
||||
|
||||
template <class... Ts>
|
||||
struct Data {
|
||||
std::vector<int> vec_;
|
||||
std::tuple<Ts...> tuple_;
|
||||
|
||||
template <class... Us>
|
||||
requires std::is_constructible_v<std::tuple<Ts...>, Us&&...>
|
||||
constexpr Data(std::initializer_list<int> il, Us&&... us) : vec_(il), tuple_(std::forward<Us>(us)...) {}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// no arg
|
||||
{
|
||||
std::expected<int, Data<>> e(std::unexpect, {1, 2, 3});
|
||||
assert(!e.has_value());
|
||||
auto expectedList = {1, 2, 3};
|
||||
assert(std::ranges::equal(e.error().vec_, expectedList));
|
||||
}
|
||||
|
||||
// one arg
|
||||
{
|
||||
std::expected<int, Data<MoveOnly>> e(std::unexpect, {4, 5, 6}, MoveOnly(5));
|
||||
assert(!e.has_value());
|
||||
auto expectedList = {4, 5, 6};
|
||||
assert((std::ranges::equal(e.error().vec_, expectedList)));
|
||||
assert(std::get<0>(e.error().tuple_) == 5);
|
||||
}
|
||||
|
||||
// multi args
|
||||
{
|
||||
int i = 5;
|
||||
int j = 6;
|
||||
MoveOnly m(7);
|
||||
std::expected<int, Data<int&, int&&, MoveOnly>> e(std::unexpect, {1, 2}, i, std::move(j), std::move(m));
|
||||
assert(!e.has_value());
|
||||
auto expectedList = {1, 2};
|
||||
assert((std::ranges::equal(e.error().vec_, expectedList)));
|
||||
assert(&std::get<0>(e.error().tuple_) == &i);
|
||||
assert(&std::get<1>(e.error().tuple_) == &j);
|
||||
assert(std::get<2>(e.error().tuple_) == 7);
|
||||
assert(m.get() == 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(std::initializer_list<int>, int) { throw Except{}; };
|
||||
};
|
||||
|
||||
try {
|
||||
std::expected<int, Throwing> u(std::unexpect, {1, 2}, 5);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class G>
|
||||
// constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
|
||||
//
|
||||
// Let GF be const G&
|
||||
//
|
||||
// Constraints: is_constructible_v<E, GF> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes unex with std::forward<GF>(e.error()).
|
||||
//
|
||||
// Postconditions: has_value() is false.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of unex.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, const std::unexpected<int>&>);
|
||||
|
||||
// !is_constructible_v<E, GF>
|
||||
struct foo {};
|
||||
static_assert(!std::is_constructible_v<std::expected<int, int>, const std::unexpected<foo>&>);
|
||||
static_assert(!std::is_constructible_v<std::expected<int, MoveOnly>, const std::unexpected<MoveOnly>&>);
|
||||
|
||||
// explicit(!is_convertible_v<const G&, E>)
|
||||
struct NotConvertible {
|
||||
explicit NotConvertible(int);
|
||||
};
|
||||
static_assert(std::is_convertible_v<const std::unexpected<int>&, std::expected<int, int>>);
|
||||
static_assert(!std::is_convertible_v<const std::unexpected<int>&, std::expected<int, NotConvertible>>);
|
||||
|
||||
struct MyInt {
|
||||
int i;
|
||||
constexpr MyInt(int ii) : i(ii) {}
|
||||
friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr void testUnexpected() {
|
||||
const std::unexpected<int> u(5);
|
||||
std::expected<int, T> e(u);
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 5);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
testUnexpected<int>();
|
||||
testUnexpected<MyInt>();
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(int) { throw Except{}; }
|
||||
};
|
||||
|
||||
{
|
||||
const std::unexpected<int> u(5);
|
||||
try {
|
||||
[[maybe_unused]] std::expected<int, Throwing> e(u);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class G>
|
||||
// constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
|
||||
//
|
||||
// Let GF be G
|
||||
//
|
||||
// Constraints: is_constructible_v<E, GF> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes unex with std::forward<GF>(e.error()).
|
||||
//
|
||||
// Postconditions: has_value() is false.
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of unex.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints
|
||||
static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpected<int>>);
|
||||
static_assert(std::is_constructible_v<std::expected<int, MoveOnly>, std::unexpected<MoveOnly>>);
|
||||
|
||||
// !is_constructible_v<E, GF>
|
||||
struct foo {};
|
||||
static_assert(!std::is_constructible_v<std::expected<int, int>, std::unexpected<foo>>);
|
||||
|
||||
// explicit(!is_convertible_v<G, E>)
|
||||
struct NotConvertible {
|
||||
explicit NotConvertible(int);
|
||||
};
|
||||
static_assert(std::is_convertible_v<std::unexpected<int>&&, std::expected<int, int>>);
|
||||
static_assert(!std::is_convertible_v<std::unexpected<int>&&, std::expected<int, NotConvertible>>);
|
||||
|
||||
struct MyInt {
|
||||
int i;
|
||||
constexpr MyInt(int ii) : i(ii) {}
|
||||
friend constexpr bool operator==(const MyInt&, const MyInt&) = default;
|
||||
};
|
||||
|
||||
template <class Err>
|
||||
constexpr void testInt() {
|
||||
std::unexpected<int> u(5);
|
||||
std::expected<int, Err> e(std::move(u));
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 5);
|
||||
}
|
||||
|
||||
constexpr void testMoveOnly() {
|
||||
std::unexpected<MoveOnly> u(MoveOnly(5));
|
||||
std::expected<int, MoveOnly> e(std::move(u));
|
||||
assert(!e.has_value());
|
||||
assert(e.error() == 5);
|
||||
assert(u.error() == 0);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
testInt<int>();
|
||||
testInt<MyInt>();
|
||||
testInt<MoveOnly>();
|
||||
testMoveOnly();
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(int) { throw Except{}; }
|
||||
};
|
||||
|
||||
{
|
||||
std::unexpected<int> u(5);
|
||||
try {
|
||||
[[maybe_unused]] std::expected<int, Throwing> e(std::move(u));
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// constexpr ~expected();
|
||||
//
|
||||
// Effects: If has_value() is true, destroys val, otherwise destroys unex.
|
||||
//
|
||||
// Remarks: If is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> is true,
|
||||
// then this destructor is a trivial destructor.
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Remarks: If is_trivially_destructible_v<T> is true, and is_trivially_destructible_v<E> is true,
|
||||
// then this destructor is a trivial destructor.
|
||||
struct NonTrivial {
|
||||
~NonTrivial() {}
|
||||
};
|
||||
|
||||
#if __cpp_concepts >= 202002
|
||||
static_assert(std::is_trivially_destructible_v<std::expected<int, int>>);
|
||||
#endif
|
||||
static_assert(!std::is_trivially_destructible_v<std::expected<NonTrivial, int>>);
|
||||
static_assert(!std::is_trivially_destructible_v<std::expected<int, NonTrivial>>);
|
||||
static_assert(!std::is_trivially_destructible_v<std::expected<NonTrivial, NonTrivial>>);
|
||||
|
||||
struct TrackedDestroy {
|
||||
bool& destroyed;
|
||||
constexpr TrackedDestroy(bool& b) : destroyed(b) {}
|
||||
constexpr ~TrackedDestroy() { destroyed = true; }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// has value
|
||||
{
|
||||
bool valueDestroyed = false;
|
||||
{ [[maybe_unused]] std::expected<TrackedDestroy, TrackedDestroy> e(std::in_place, valueDestroyed); }
|
||||
assert(valueDestroyed);
|
||||
}
|
||||
|
||||
// has error
|
||||
{
|
||||
bool errorDestroyed = false;
|
||||
{ [[maybe_unused]] std::expected<TrackedDestroy, TrackedDestroy> e(std::unexpect, errorDestroyed); }
|
||||
assert(errorDestroyed);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Data {
|
||||
int i;
|
||||
constexpr Data(int ii) : i(ii) {}
|
||||
|
||||
friend constexpr bool operator==(const Data& data, int ii) { return data.i == ii; }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// x.has_value()
|
||||
{
|
||||
const std::expected<Data, int> e1(std::in_place, 5);
|
||||
int i2 = 10;
|
||||
int i3 = 5;
|
||||
assert(e1 != i2);
|
||||
assert(e1 == i3);
|
||||
}
|
||||
|
||||
// !x.has_value()
|
||||
{
|
||||
const std::expected<Data, int> e1(std::unexpect, 5);
|
||||
int i2 = 10;
|
||||
int i3 = 5;
|
||||
assert(e1 != i2);
|
||||
assert(e1 != i3);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class T2, class E2> requires (!is_void_v<T2>)
|
||||
// friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test constraint
|
||||
template <class T1, class T2>
|
||||
concept CanCompare = requires(T1 t1, T2 t2) { t1 == t2; };
|
||||
|
||||
struct Foo{};
|
||||
static_assert(!CanCompare<Foo, Foo>);
|
||||
|
||||
static_assert(CanCompare<std::expected<int, int>, std::expected<int, int>>);
|
||||
static_assert(CanCompare<std::expected<int, int>, std::expected<short, short>>);
|
||||
|
||||
// Note this is true because other overloads are unconstrained
|
||||
static_assert(CanCompare<std::expected<int, int>, std::expected<void, int>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// x.has_value() && y.has_value()
|
||||
{
|
||||
const std::expected<int, int> e1(5);
|
||||
const std::expected<int, int> e2(10);
|
||||
const std::expected<int, int> e3(5);
|
||||
assert(e1 != e2);
|
||||
assert(e1 == e3);
|
||||
}
|
||||
|
||||
// !x.has_value() && y.has_value()
|
||||
{
|
||||
const std::expected<int, int> e1(std::unexpect, 5);
|
||||
const std::expected<int, int> e2(10);
|
||||
const std::expected<int, int> e3(5);
|
||||
assert(e1 != e2);
|
||||
assert(e1 != e3);
|
||||
}
|
||||
|
||||
// x.has_value() && !y.has_value()
|
||||
{
|
||||
const std::expected<int, int> e1(5);
|
||||
const std::expected<int, int> e2(std::unexpect, 10);
|
||||
const std::expected<int, int> e3(std::unexpect, 5);
|
||||
assert(e1 != e2);
|
||||
assert(e1 != e3);
|
||||
}
|
||||
|
||||
// !x.has_value() && !y.has_value()
|
||||
{
|
||||
const std::expected<int, int> e1(std::unexpect, 5);
|
||||
const std::expected<int, int> e2(std::unexpect, 10);
|
||||
const std::expected<int, int> e3(std::unexpect, 5);
|
||||
assert(e1 != e2);
|
||||
assert(e1 == e3);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Data {
|
||||
int i;
|
||||
constexpr Data(int ii) : i(ii) {}
|
||||
|
||||
friend constexpr bool operator==(const Data& data, int ii) { return data.i == ii; }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// x.has_value()
|
||||
{
|
||||
const std::expected<Data, Data> e1(std::in_place, 5);
|
||||
std::unexpected<int> un2(10);
|
||||
std::unexpected<int> un3(5);
|
||||
assert(e1 != un2);
|
||||
assert(e1 != un3);
|
||||
}
|
||||
|
||||
// !x.has_value()
|
||||
{
|
||||
const std::expected<Data, Data> e1(std::unexpect, 5);
|
||||
std::unexpected<int> un2(10);
|
||||
std::unexpected<int> un3(5);
|
||||
assert(e1 != un2);
|
||||
assert(e1 == un3);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr const T* operator->() const noexcept;
|
||||
// constexpr T* operator->() noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test noexcept
|
||||
template <class T>
|
||||
concept ArrowNoexcept =
|
||||
requires(T t) {
|
||||
{ t.operator->() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!ArrowNoexcept<int>);
|
||||
|
||||
static_assert(ArrowNoexcept<std::expected<int, int>>);
|
||||
static_assert(ArrowNoexcept<const std::expected<int, int>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// const
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
std::same_as<const int*> decltype(auto) x = e.operator->();
|
||||
assert(x == &(e.value()));
|
||||
assert(*x == 5);
|
||||
}
|
||||
|
||||
// non-const
|
||||
{
|
||||
std::expected<int, int> e(5);
|
||||
std::same_as<int*> decltype(auto) x = e.operator->();
|
||||
assert(x == &(e.value()));
|
||||
assert(*x == 5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr explicit operator bool() const noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test noexcept
|
||||
template <class T>
|
||||
concept OpBoolNoexcept =
|
||||
requires(T t) {
|
||||
{ static_cast<bool>(t) } noexcept;
|
||||
};
|
||||
|
||||
struct Foo {};
|
||||
static_assert(!OpBoolNoexcept<Foo>);
|
||||
|
||||
static_assert(OpBoolNoexcept<std::expected<int, int>>);
|
||||
static_assert(OpBoolNoexcept<const std::expected<int, int>>);
|
||||
|
||||
// Test explicit
|
||||
static_assert(!std::is_convertible_v<std::expected<int, int>, bool>);
|
||||
|
||||
constexpr bool test() {
|
||||
// has_value
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
assert(static_cast<bool>(e));
|
||||
}
|
||||
|
||||
// !has_value
|
||||
{
|
||||
const std::expected<int, int> e(std::unexpect, 5);
|
||||
assert(!static_cast<bool>(e));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr const T& operator*() const & noexcept;
|
||||
// constexpr T& operator*() & noexcept;
|
||||
// constexpr T&& operator*() && noexcept;
|
||||
// constexpr const T&& operator*() const && noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test noexcept
|
||||
template <class T>
|
||||
concept DerefNoexcept =
|
||||
requires(T t) {
|
||||
{ std::forward<T>(t).operator*() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!DerefNoexcept<int>);
|
||||
|
||||
static_assert(DerefNoexcept<std::expected<int, int>&>);
|
||||
static_assert(DerefNoexcept<const std::expected<int, int>&>);
|
||||
static_assert(DerefNoexcept<std::expected<int, int>&&>);
|
||||
static_assert(DerefNoexcept<const std::expected<int, int>&&>);
|
||||
|
||||
constexpr bool test() {
|
||||
// non-const &
|
||||
{
|
||||
std::expected<int, int> e(5);
|
||||
decltype(auto) x = *e;
|
||||
static_assert(std::same_as<decltype(x), int&>);
|
||||
assert(&x == &(e.value()));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// const &
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
decltype(auto) x = *e;
|
||||
static_assert(std::same_as<decltype(x), const int&>);
|
||||
assert(&x == &(e.value()));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// non-const &&
|
||||
{
|
||||
std::expected<int, int> e(5);
|
||||
decltype(auto) x = *std::move(e);
|
||||
static_assert(std::same_as<decltype(x), int&&>);
|
||||
assert(&x == &(e.value()));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// const &&
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
decltype(auto) x = *std::move(e);
|
||||
static_assert(std::same_as<decltype(x), const int&&>);
|
||||
assert(&x == &(e.value()));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr const E& error() const & noexcept;
|
||||
// constexpr E& error() & noexcept;
|
||||
// constexpr E&& error() && noexcept;
|
||||
// constexpr const E&& error() const && noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test noexcept
|
||||
template <class T>
|
||||
concept ErrorNoexcept =
|
||||
requires(T t) {
|
||||
{ std::forward<T>(t).error() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!ErrorNoexcept<int>);
|
||||
|
||||
static_assert(ErrorNoexcept<std::expected<int, int>&>);
|
||||
static_assert(ErrorNoexcept<const std::expected<int, int>&>);
|
||||
static_assert(ErrorNoexcept<std::expected<int, int>&&>);
|
||||
static_assert(ErrorNoexcept<const std::expected<int, int>&&>);
|
||||
|
||||
constexpr bool test() {
|
||||
// non-const &
|
||||
{
|
||||
std::expected<int, int> e(std::unexpect, 5);
|
||||
decltype(auto) x = e.error();
|
||||
static_assert(std::same_as<decltype(x), int&>);
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// const &
|
||||
{
|
||||
const std::expected<int, int> e(std::unexpect, 5);
|
||||
decltype(auto) x = e.error();
|
||||
static_assert(std::same_as<decltype(x), const int&>);
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// non-const &&
|
||||
{
|
||||
std::expected<int, int> e(std::unexpect, 5);
|
||||
decltype(auto) x = std::move(e).error();
|
||||
static_assert(std::same_as<decltype(x), int&&>);
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// const &&
|
||||
{
|
||||
const std::expected<int, int> e(std::unexpect, 5);
|
||||
decltype(auto) x = std::move(e).error();
|
||||
static_assert(std::same_as<decltype(x), const int&&>);
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr bool has_value() const noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test noexcept
|
||||
template <class T>
|
||||
concept HasValueNoexcept =
|
||||
requires(T t) {
|
||||
{ t.has_value() } noexcept;
|
||||
};
|
||||
|
||||
struct Foo {};
|
||||
static_assert(!HasValueNoexcept<Foo>);
|
||||
|
||||
static_assert(HasValueNoexcept<std::expected<int, int>>);
|
||||
static_assert(HasValueNoexcept<const std::expected<int, int>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// has_value
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
assert(e.has_value());
|
||||
}
|
||||
|
||||
// !has_value
|
||||
{
|
||||
const std::expected<int, int> e(std::unexpect, 5);
|
||||
assert(!e.has_value());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr const T& value() const &;
|
||||
// constexpr T& value() &;
|
||||
// constexpr T&& value() &&;
|
||||
// constexpr const T&& value() const &&;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
constexpr bool test() {
|
||||
// non-const &
|
||||
{
|
||||
std::expected<int, int> e(5);
|
||||
decltype(auto) x = e.value();
|
||||
static_assert(std::same_as<decltype(x), int&>);
|
||||
assert(&x == &(*e));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// const &
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
decltype(auto) x = e.value();
|
||||
static_assert(std::same_as<decltype(x), const int&>);
|
||||
assert(&x == &(*e));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// non-const &&
|
||||
{
|
||||
std::expected<int, int> e(5);
|
||||
decltype(auto) x = std::move(e).value();
|
||||
static_assert(std::same_as<decltype(x), int&&>);
|
||||
assert(&x == &(*e));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// const &&
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
decltype(auto) x = std::move(e).value();
|
||||
static_assert(std::same_as<decltype(x), const int&&>);
|
||||
assert(&x == &(*e));
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
|
||||
// int
|
||||
{
|
||||
const std::expected<int, int> e(std::unexpect, 5);
|
||||
try {
|
||||
e.value();
|
||||
assert(false);
|
||||
} catch (const std::bad_expected_access<int>& ex) {
|
||||
assert(ex.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
// MoveOnly
|
||||
{
|
||||
std::expected<int, MoveOnly> e(std::unexpect, 5);
|
||||
try {
|
||||
std::move(e).value();
|
||||
assert(false);
|
||||
} catch (const std::bad_expected_access<MoveOnly>& ex) {
|
||||
assert(ex.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class U> constexpr T value_or(U&& v) const &;
|
||||
// template<class U> constexpr T value_or(U&& v) &&;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "MoveOnly.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
constexpr bool test() {
|
||||
// const &, has_value()
|
||||
{
|
||||
const std::expected<int, int> e(5);
|
||||
std::same_as<int> decltype(auto) x = e.value_or(10);
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// const &, !has_value()
|
||||
{
|
||||
const std::expected<int, int> e(std::unexpect, 5);
|
||||
std::same_as<int> decltype(auto) x = e.value_or(10);
|
||||
assert(x == 10);
|
||||
}
|
||||
|
||||
// &&, has_value()
|
||||
{
|
||||
std::expected<MoveOnly, int> e(std::in_place, 5);
|
||||
std::same_as<MoveOnly> decltype(auto) x = std::move(e).value_or(10);
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
// &&, !has_value()
|
||||
{
|
||||
std::expected<MoveOnly, int> e(std::unexpect, 5);
|
||||
std::same_as<MoveOnly> decltype(auto) x = std::move(e).value_or(10);
|
||||
assert(x == 10);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
|
||||
// int
|
||||
{
|
||||
const std::expected<int, int> e(std::unexpect, 5);
|
||||
try {
|
||||
e.value();
|
||||
assert(false);
|
||||
} catch (const std::bad_expected_access<int>& ex) {
|
||||
assert(ex.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
// MoveOnly
|
||||
{
|
||||
std::expected<int, MoveOnly> e(std::unexpect, 5);
|
||||
try {
|
||||
std::move(e).value();
|
||||
assert(false);
|
||||
} catch (const std::bad_expected_access<MoveOnly>& ex) {
|
||||
assert(ex.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, clang-15, apple-clang-14
|
||||
|
||||
// friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
struct NotSwappable {
|
||||
NotSwappable operator=(const NotSwappable&) = delete;
|
||||
};
|
||||
void swap(NotSwappable&, NotSwappable&) = delete;
|
||||
|
||||
static_assert(std::is_swappable_v<std::expected<int, int>>);
|
||||
|
||||
// !is_swappable_v<T>
|
||||
static_assert(!std::is_swappable_v<std::expected<NotSwappable, int>>);
|
||||
|
||||
// !is_swappable_v<E>
|
||||
static_assert(!std::is_swappable_v<std::expected<int, NotSwappable>>);
|
||||
|
||||
struct NotMoveContructible {
|
||||
NotMoveContructible(NotMoveContructible&&) = delete;
|
||||
friend void swap(NotMoveContructible&, NotMoveContructible&) {}
|
||||
};
|
||||
|
||||
// !is_move_constructible_v<T>
|
||||
static_assert(!std::is_swappable_v<std::expected<NotMoveContructible, int>>);
|
||||
|
||||
// !is_move_constructible_v<E>
|
||||
static_assert(!std::is_swappable_v<std::expected<int, NotMoveContructible>>);
|
||||
|
||||
struct MoveMayThrow {
|
||||
MoveMayThrow(MoveMayThrow&&) noexcept(false);
|
||||
friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {}
|
||||
};
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_swappable_v<std::expected<MoveMayThrow, int>>);
|
||||
|
||||
// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(std::is_swappable_v<std::expected<int, MoveMayThrow>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_swappable_v<std::expected<MoveMayThrow, MoveMayThrow>>);
|
||||
|
||||
// Test noexcept
|
||||
static_assert(std::is_nothrow_swappable_v<std::expected<int, int>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T>
|
||||
static_assert(!std::is_nothrow_swappable_v<std::expected<MoveMayThrow, int>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_nothrow_swappable_v<std::expected<int, MoveMayThrow>>);
|
||||
|
||||
struct SwapMayThrow {
|
||||
friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {}
|
||||
};
|
||||
|
||||
// !is_nothrow_swappable_v<T>
|
||||
static_assert(!std::is_nothrow_swappable_v<std::expected<SwapMayThrow, int>>);
|
||||
|
||||
// !is_nothrow_swappable_v<E>
|
||||
static_assert(!std::is_nothrow_swappable_v<std::expected<int, SwapMayThrow>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// this->has_value() && rhs.has_value()
|
||||
{
|
||||
std::expected<ADLSwap, int> x(std::in_place, 5);
|
||||
std::expected<ADLSwap, int> y(std::in_place, 10);
|
||||
swap(x, y);
|
||||
|
||||
assert(x.has_value());
|
||||
assert(x->i == 10);
|
||||
assert(x->adlSwapCalled);
|
||||
assert(y.has_value());
|
||||
assert(y->i == 5);
|
||||
assert(y->adlSwapCalled);
|
||||
}
|
||||
|
||||
// !this->has_value() && !rhs.has_value()
|
||||
{
|
||||
std::expected<int, ADLSwap> x(std::unexpect, 5);
|
||||
std::expected<int, ADLSwap> y(std::unexpect, 10);
|
||||
swap(x, y);
|
||||
|
||||
assert(!x.has_value());
|
||||
assert(x.error().i == 10);
|
||||
assert(x.error().adlSwapCalled);
|
||||
assert(!y.has_value());
|
||||
assert(y.error().i == 5);
|
||||
assert(y.error().adlSwapCalled);
|
||||
}
|
||||
|
||||
// this->has_value() && !rhs.has_value()
|
||||
// && is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::in_place, 5);
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e2(std::unexpect, 10);
|
||||
|
||||
swap(e1, e2);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().i == 10);
|
||||
assert(e2.has_value());
|
||||
assert(e2->i == 5);
|
||||
|
||||
assert(e1.error().numberOfMoves == 2);
|
||||
assert(!e1.error().swapCalled);
|
||||
assert(e2->numberOfMoves == 1);
|
||||
assert(!e2->swapCalled);
|
||||
}
|
||||
|
||||
// this->has_value() && !rhs.has_value()
|
||||
// && !is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::in_place, 5);
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e2(std::unexpect, 10);
|
||||
|
||||
e1.swap(e2);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().i == 10);
|
||||
assert(e2.has_value());
|
||||
assert(e2->i == 5);
|
||||
|
||||
assert(e1.error().numberOfMoves == 1);
|
||||
assert(!e1.error().swapCalled);
|
||||
assert(e2->numberOfMoves == 2);
|
||||
assert(!e2->swapCalled);
|
||||
}
|
||||
|
||||
// !this->has_value() && rhs.has_value()
|
||||
// && is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::unexpect, 10);
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e2(std::in_place, 5);
|
||||
|
||||
swap(e1, e2);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1->i == 5);
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().i == 10);
|
||||
|
||||
assert(e1->numberOfMoves == 1);
|
||||
assert(!e1->swapCalled);
|
||||
assert(e2.error().numberOfMoves == 2);
|
||||
assert(!e2.error().swapCalled);
|
||||
}
|
||||
|
||||
// !this->has_value() && rhs.has_value()
|
||||
// && !is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::unexpect, 10);
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e2(std::in_place, 5);
|
||||
|
||||
swap(e1, e2);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1->i == 5);
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().i == 10);
|
||||
|
||||
assert(e1->numberOfMoves == 2);
|
||||
assert(!e1->swapCalled);
|
||||
assert(e2.error().numberOfMoves == 1);
|
||||
assert(!e2.error().swapCalled);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
// !e1.has_value() && e2.has_value()
|
||||
{
|
||||
std::expected<ThrowOnMoveConstruct, int> e1(std::unexpect, 5);
|
||||
std::expected<ThrowOnMoveConstruct, int> e2(std::in_place);
|
||||
try {
|
||||
swap(e1, e2);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
// e1.has_value() && !e2.has_value()
|
||||
{
|
||||
std::expected<int, ThrowOnMoveConstruct> e1(5);
|
||||
std::expected<int, ThrowOnMoveConstruct> e2(std::unexpect);
|
||||
try {
|
||||
swap(e1, e2);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
assert(*e1 == 5);
|
||||
}
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,239 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr void swap(expected& rhs) noexcept(see below);
|
||||
//
|
||||
// Constraints:
|
||||
// is_swappable_v<T> is true and
|
||||
// is_swappable_v<E> is true and
|
||||
// is_move_constructible_v<T> && is_move_constructible_v<E> is true, and
|
||||
// is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E> is true.
|
||||
//
|
||||
// Throws: Any exception thrown by the expressions in the Effects.
|
||||
// Remarks: The exception specification is equivalent to:
|
||||
// is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T> &&
|
||||
// is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
template <class T, class E>
|
||||
concept HasMemberSwap = requires(std::expected<T, E> x, std::expected<T, E> y) { x.swap(y); };
|
||||
|
||||
static_assert(HasMemberSwap<int, int>);
|
||||
|
||||
struct NotSwappable {};
|
||||
void swap(NotSwappable&, NotSwappable&) = delete;
|
||||
|
||||
// !is_swappable_v<T>
|
||||
static_assert(!HasMemberSwap<NotSwappable, int>);
|
||||
|
||||
// !is_swappable_v<E>
|
||||
static_assert(!HasMemberSwap<int, NotSwappable>);
|
||||
|
||||
struct NotMoveContructible {
|
||||
NotMoveContructible(NotMoveContructible&&) = delete;
|
||||
friend void swap(NotMoveContructible&, NotMoveContructible&) {}
|
||||
};
|
||||
|
||||
// !is_move_constructible_v<T>
|
||||
static_assert(!HasMemberSwap<NotMoveContructible, int>);
|
||||
|
||||
// !is_move_constructible_v<E>
|
||||
static_assert(!HasMemberSwap<int, NotMoveContructible>);
|
||||
|
||||
struct MoveMayThrow {
|
||||
MoveMayThrow(MoveMayThrow&&) noexcept(false);
|
||||
friend void swap(MoveMayThrow&, MoveMayThrow&) noexcept {}
|
||||
};
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>
|
||||
static_assert(HasMemberSwap<MoveMayThrow, int>);
|
||||
|
||||
// is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(HasMemberSwap<int, MoveMayThrow>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T> && !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!HasMemberSwap<MoveMayThrow, MoveMayThrow>);
|
||||
|
||||
// Test noexcept
|
||||
template <class T, class E>
|
||||
concept MemberSwapNoexcept =
|
||||
requires(std::expected<T, E> x, std::expected<T, E> y) {
|
||||
{ x.swap(y) } noexcept;
|
||||
};
|
||||
|
||||
static_assert(MemberSwapNoexcept<int, int>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<T>
|
||||
static_assert(!MemberSwapNoexcept<MoveMayThrow, int>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!MemberSwapNoexcept<int, MoveMayThrow>);
|
||||
|
||||
struct SwapMayThrow {
|
||||
friend void swap(SwapMayThrow&, SwapMayThrow&) noexcept(false) {}
|
||||
};
|
||||
|
||||
// !is_nothrow_swappable_v<T>
|
||||
static_assert(!MemberSwapNoexcept<SwapMayThrow, int>);
|
||||
|
||||
// !is_nothrow_swappable_v<E>
|
||||
static_assert(!MemberSwapNoexcept<int, SwapMayThrow>);
|
||||
|
||||
constexpr bool test() {
|
||||
// this->has_value() && rhs.has_value()
|
||||
{
|
||||
std::expected<ADLSwap, int> x(std::in_place, 5);
|
||||
std::expected<ADLSwap, int> y(std::in_place, 10);
|
||||
x.swap(y);
|
||||
|
||||
assert(x.has_value());
|
||||
assert(x->i == 10);
|
||||
assert(x->adlSwapCalled);
|
||||
assert(y.has_value());
|
||||
assert(y->i == 5);
|
||||
assert(y->adlSwapCalled);
|
||||
}
|
||||
|
||||
// !this->has_value() && !rhs.has_value()
|
||||
{
|
||||
std::expected<int, ADLSwap> x(std::unexpect, 5);
|
||||
std::expected<int, ADLSwap> y(std::unexpect, 10);
|
||||
x.swap(y);
|
||||
|
||||
assert(!x.has_value());
|
||||
assert(x.error().i == 10);
|
||||
assert(x.error().adlSwapCalled);
|
||||
assert(!y.has_value());
|
||||
assert(y.error().i == 5);
|
||||
assert(y.error().adlSwapCalled);
|
||||
}
|
||||
|
||||
// this->has_value() && !rhs.has_value()
|
||||
// && is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::in_place, 5);
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e2(std::unexpect, 10);
|
||||
|
||||
e1.swap(e2);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().i == 10);
|
||||
assert(e2.has_value());
|
||||
assert(e2->i == 5);
|
||||
|
||||
assert(e1.error().numberOfMoves == 2);
|
||||
assert(!e1.error().swapCalled);
|
||||
assert(e2->numberOfMoves == 1);
|
||||
assert(!e2->swapCalled);
|
||||
}
|
||||
|
||||
// this->has_value() && !rhs.has_value()
|
||||
// && !is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::in_place, 5);
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e2(std::unexpect, 10);
|
||||
|
||||
e1.swap(e2);
|
||||
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().i == 10);
|
||||
assert(e2.has_value());
|
||||
assert(e2->i == 5);
|
||||
|
||||
assert(e1.error().numberOfMoves == 1);
|
||||
assert(!e1.error().swapCalled);
|
||||
assert(e2->numberOfMoves == 2);
|
||||
assert(!e2->swapCalled);
|
||||
}
|
||||
|
||||
// !this->has_value() && rhs.has_value()
|
||||
// && is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e1(std::unexpect, 10);
|
||||
std::expected<TrackedMove<true>, TrackedMove<true>> e2(std::in_place, 5);
|
||||
|
||||
e1.swap(e2);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1->i == 5);
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().i == 10);
|
||||
|
||||
assert(e1->numberOfMoves == 1);
|
||||
assert(!e1->swapCalled);
|
||||
assert(e2.error().numberOfMoves == 2);
|
||||
assert(!e2.error().swapCalled);
|
||||
}
|
||||
|
||||
// !this->has_value() && rhs.has_value()
|
||||
// && !is_nothrow_move_constructible_v<E>
|
||||
{
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e1(std::unexpect, 10);
|
||||
std::expected<TrackedMove<true>, TrackedMove<false>> e2(std::in_place, 5);
|
||||
|
||||
e1.swap(e2);
|
||||
|
||||
assert(e1.has_value());
|
||||
assert(e1->i == 5);
|
||||
assert(!e2.has_value());
|
||||
assert(e2.error().i == 10);
|
||||
|
||||
assert(e1->numberOfMoves == 2);
|
||||
assert(!e1->swapCalled);
|
||||
assert(e2.error().numberOfMoves == 1);
|
||||
assert(!e2.error().swapCalled);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
// !e1.has_value() && e2.has_value()
|
||||
{
|
||||
std::expected<ThrowOnMoveConstruct, int> e1(std::unexpect, 5);
|
||||
std::expected<ThrowOnMoveConstruct, int> e2(std::in_place);
|
||||
try {
|
||||
e1.swap(e2);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error() == 5);
|
||||
}
|
||||
}
|
||||
|
||||
// e1.has_value() && !e2.has_value()
|
||||
{
|
||||
std::expected<int, ThrowOnMoveConstruct> e1(5);
|
||||
std::expected<int, ThrowOnMoveConstruct> e2(std::unexpect);
|
||||
try {
|
||||
e1.swap(e2);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
assert(*e1 == 5);
|
||||
}
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr unexpected& operator=(const unexpected&) = default;
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
|
||||
struct Error {
|
||||
int i;
|
||||
constexpr Error(int ii) : i(ii) {}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
std::unexpected<Error> unex1(4);
|
||||
const std::unexpected<Error> unex2(5);
|
||||
unex1 = unex2;
|
||||
assert(unex1.error().i == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr unexpected& operator=(unexpected&&) = default;
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
struct Error {
|
||||
int i;
|
||||
constexpr Error(int ii) : i(ii) {}
|
||||
constexpr Error& operator=(Error&& other) {
|
||||
i = other.i;
|
||||
other.i = 0;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
std::unexpected<Error> unex1(4);
|
||||
std::unexpected<Error> unex2(5);
|
||||
unex1 = std::move(unex2);
|
||||
assert(unex1.error().i == 5);
|
||||
assert(unex2.error().i == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class E> unexpected(E) -> unexpected<E>;
|
||||
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
|
||||
struct Foo{};
|
||||
|
||||
static_assert(std::same_as<decltype(std::unexpected(5)), std::unexpected<int>>);
|
||||
static_assert(std::same_as<decltype(std::unexpected(Foo{})), std::unexpected<Foo>>);
|
||||
static_assert(std::same_as<decltype(std::unexpected(std::unexpected<int>(5))), std::unexpected<int>>);
|
@ -0,0 +1,31 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr unexpected(const unexpected&) = default;
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
|
||||
struct Error {
|
||||
int i;
|
||||
constexpr Error(int ii) : i(ii) {}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
const std::unexpected<Error> unex(5);
|
||||
auto unex2 = unex;
|
||||
assert(unex2.error().i == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class Err = E>
|
||||
// constexpr explicit unexpected(Err&& e);
|
||||
//
|
||||
// Constraints:
|
||||
// - is_same_v<remove_cvref_t<Err>, unexpected> is false; and
|
||||
// - is_same_v<remove_cvref_t<Err>, in_place_t> is false; and
|
||||
// - is_constructible_v<E, Err> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes unex with std::forward<Err>(e).
|
||||
// Throws: Any exception thrown by the initialization of unex.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(std::constructible_from<std::unexpected<int>, int>);
|
||||
|
||||
// is_same_v<remove_cvref_t<Err>, unexpected>
|
||||
struct CstrFromUnexpected {
|
||||
CstrFromUnexpected(CstrFromUnexpected const&) = delete;
|
||||
CstrFromUnexpected(std::unexpected<CstrFromUnexpected> const&);
|
||||
};
|
||||
static_assert(!std::constructible_from<std::unexpected<CstrFromUnexpected>, std::unexpected<CstrFromUnexpected>>);
|
||||
|
||||
// is_same_v<remove_cvref_t<Err>, in_place_t>
|
||||
struct CstrFromInplace {
|
||||
CstrFromInplace(std::in_place_t);
|
||||
};
|
||||
static_assert(!std::constructible_from<std::unexpected<CstrFromInplace>, std::in_place_t>);
|
||||
|
||||
// !is_constructible_v<E, Err>
|
||||
struct Foo {};
|
||||
static_assert(!std::constructible_from<std::unexpected<Foo>, int>);
|
||||
|
||||
// test explicit
|
||||
static_assert(std::convertible_to<int, int>);
|
||||
static_assert(!std::convertible_to<int, std::unexpected<int>>);
|
||||
|
||||
struct Error {
|
||||
int i;
|
||||
constexpr Error(int ii) : i(ii) {}
|
||||
constexpr Error(const Error& other) : i(other.i) {}
|
||||
constexpr Error(Error&& other) : i(other.i) { other.i = 0; }
|
||||
Error(std::initializer_list<Error>) { assert(false); }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// lvalue
|
||||
{
|
||||
Error e(5);
|
||||
std::unexpected<Error> unex(e);
|
||||
assert(unex.error().i == 5);
|
||||
assert(e.i == 5);
|
||||
}
|
||||
|
||||
// rvalue
|
||||
{
|
||||
Error e(5);
|
||||
std::unexpected<Error> unex(std::move(e));
|
||||
assert(unex.error().i == 5);
|
||||
assert(e.i == 0);
|
||||
}
|
||||
|
||||
// Direct-non-list-initializes: does not trigger initializer_list overload
|
||||
{
|
||||
Error e(5);
|
||||
[[maybe_unused]] std::unexpected<Error> unex(e);
|
||||
}
|
||||
|
||||
// Test default template argument.
|
||||
// Without it, the template parameter cannot be deduced from an initializer list
|
||||
{
|
||||
struct Bar {
|
||||
int i;
|
||||
int j;
|
||||
constexpr Bar(int ii, int jj) : i(ii), j(jj) {}
|
||||
};
|
||||
std::unexpected<Bar> ue({5, 6});
|
||||
assert(ue.error().i == 5);
|
||||
assert(ue.error().j == 6);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing() = default;
|
||||
Throwing(const Throwing&) { throw Except{}; }
|
||||
};
|
||||
|
||||
Throwing t;
|
||||
try {
|
||||
std::unexpected<Throwing> u(t);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class... Args>
|
||||
// constexpr explicit unexpected(in_place_t, Args&&... args);
|
||||
//
|
||||
// Constraints: is_constructible_v<E, Args...> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of unex.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(std::constructible_from<std::unexpected<int>, std::in_place_t, int>);
|
||||
|
||||
// !is_constructible_v<E, Args...>
|
||||
struct Foo {};
|
||||
static_assert(!std::constructible_from<std::unexpected<Foo>, std::in_place_t, int>);
|
||||
|
||||
// test explicit
|
||||
template <class T>
|
||||
void conversion_test(T);
|
||||
|
||||
template <class T, class... Args>
|
||||
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
|
||||
|
||||
static_assert(ImplicitlyConstructible<int, int>);
|
||||
static_assert(!ImplicitlyConstructible<std::unexpected<int>, std::in_place_t, int>);
|
||||
|
||||
struct Arg {
|
||||
int i;
|
||||
constexpr Arg(int ii) : i(ii) {}
|
||||
constexpr Arg(const Arg& other) : i(other.i) {}
|
||||
constexpr Arg(Arg&& other) : i(other.i) { other.i = 0; }
|
||||
};
|
||||
|
||||
struct Error {
|
||||
Arg arg;
|
||||
constexpr explicit Error(const Arg& a) : arg(a) {}
|
||||
constexpr explicit Error(Arg&& a) : arg(std::move(a)) {}
|
||||
Error(std::initializer_list<Error>) :arg(0){ assert(false); }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// lvalue
|
||||
{
|
||||
Arg a{5};
|
||||
std::unexpected<Error> unex(std::in_place, a);
|
||||
assert(unex.error().arg.i == 5);
|
||||
assert(a.i == 5);
|
||||
}
|
||||
|
||||
// rvalue
|
||||
{
|
||||
Arg a{5};
|
||||
std::unexpected<Error> unex(std::in_place, std::move(a));
|
||||
assert(unex.error().arg.i == 5);
|
||||
assert(a.i == 0);
|
||||
}
|
||||
|
||||
// Direct-non-list-initializes: does not trigger initializer_list overload
|
||||
{
|
||||
Error e(5);
|
||||
[[maybe_unused]] std::unexpected<Error> unex(std::in_place, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(int) { throw Except{}; }
|
||||
};
|
||||
|
||||
try {
|
||||
std::unexpected<Throwing> u(std::in_place, 5);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class U, class... Args>
|
||||
// constexpr explicit unexpected(in_place_t, initializer_list<U> il, Args&&... args);
|
||||
//
|
||||
// Constraints: is_constructible_v<E, initializer_list<U>&, Args...> is true.
|
||||
//
|
||||
// Effects: Direct-non-list-initializes unex with il, std::forward<Args>(args)....
|
||||
//
|
||||
// Throws: Any exception thrown by the initialization of unex.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Arg {
|
||||
int i;
|
||||
constexpr Arg(int ii) : i(ii) {}
|
||||
constexpr Arg(const Arg& other) : i(other.i) {}
|
||||
constexpr Arg(Arg&& other) : i(other.i) { other.i = 0; }
|
||||
};
|
||||
|
||||
struct Error {
|
||||
std::initializer_list<int> list;
|
||||
Arg arg;
|
||||
constexpr explicit Error(std::initializer_list<int> l, const Arg& a) : list(l), arg(a) {}
|
||||
constexpr explicit Error(std::initializer_list<int> l, Arg&& a) : list(l), arg(std::move(a)) {}
|
||||
};
|
||||
|
||||
// Test Constraints:
|
||||
static_assert(std::constructible_from<std::unexpected<Error>, std::in_place_t, std::initializer_list<int>, Arg>);
|
||||
|
||||
// !is_constructible_v<E, initializer_list<U>&, Args...>
|
||||
struct Foo {};
|
||||
static_assert(!std::constructible_from<std::unexpected<Error>, std::in_place_t, std::initializer_list<double>, Arg>);
|
||||
|
||||
// test explicit
|
||||
template <class T>
|
||||
void conversion_test(T);
|
||||
|
||||
template <class T, class... Args>
|
||||
concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
|
||||
|
||||
static_assert(ImplicitlyConstructible<int, int>);
|
||||
static_assert(!ImplicitlyConstructible<std::unexpected<Error>, std::in_place_t, std::initializer_list<int>, Arg>);
|
||||
|
||||
constexpr bool test() {
|
||||
// lvalue
|
||||
{
|
||||
Arg a{5};
|
||||
auto l = {1, 2, 3};
|
||||
std::unexpected<Error> unex(std::in_place, l, a);
|
||||
assert(unex.error().arg.i == 5);
|
||||
assert(std::ranges::equal(unex.error().list, l));
|
||||
assert(a.i == 5);
|
||||
}
|
||||
|
||||
// rvalue
|
||||
{
|
||||
Arg a{5};
|
||||
auto l = {1, 2, 3};
|
||||
std::unexpected<Error> unex(std::in_place, l, std::move(a));
|
||||
assert(unex.error().arg.i == 5);
|
||||
assert(std::ranges::equal(unex.error().list, l));
|
||||
assert(a.i == 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Except {};
|
||||
|
||||
struct Throwing {
|
||||
Throwing(std::initializer_list<int>, int) { throw Except{}; }
|
||||
};
|
||||
|
||||
try {
|
||||
std::unexpected<Throwing> u(std::in_place, {1, 2}, 5);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr unexpected(unexpected&&) = default;
|
||||
|
||||
#include <cassert>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
struct Error {
|
||||
int i;
|
||||
constexpr Error(int ii) : i(ii) {}
|
||||
constexpr Error(Error&& other) : i(other.i) {other.i = 0;}
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
std::unexpected<Error> unex(5);
|
||||
auto unex2 = std::move(unex);
|
||||
assert(unex2.error().i == 5);
|
||||
assert(unex.error().i == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// template<class E2>
|
||||
// friend constexpr bool operator==(const unexpected& x, const unexpected<E2>& y);
|
||||
//
|
||||
// Mandates: The expression x.error() == y.error() is well-formed and its result is convertible to bool.
|
||||
//
|
||||
// Returns: x.error() == y.error().
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
struct Error{
|
||||
int i;
|
||||
friend constexpr bool operator==(const Error&, const Error&) = default;
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
std::unexpected<Error> unex1(Error{2});
|
||||
std::unexpected<Error> unex2(Error{3});
|
||||
std::unexpected<Error> unex3(Error{2});
|
||||
assert(unex1 == unex3);
|
||||
assert(unex1 != unex2);
|
||||
assert(unex2 != unex3);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr const E& error() const & noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
template <class T>
|
||||
concept ErrorNoexcept =
|
||||
requires(const T& t) {
|
||||
{ t.error() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!ErrorNoexcept<int>);
|
||||
static_assert(ErrorNoexcept<std::unexpected<int>>);
|
||||
|
||||
constexpr bool test() {
|
||||
const std::unexpected<int> unex(5);
|
||||
decltype(auto) i = unex.error();
|
||||
static_assert(std::same_as<decltype(i), const int&>);
|
||||
assert(i == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr const E&& error() const && noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
template <class T>
|
||||
concept ErrorNoexcept =
|
||||
requires(const T&& t) {
|
||||
{ std::move(t).error() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!ErrorNoexcept<int>);
|
||||
static_assert(ErrorNoexcept<std::unexpected<int>>);
|
||||
|
||||
constexpr bool test() {
|
||||
const std::unexpected<int> unex(5);
|
||||
decltype(auto) i = std::move(unex).error();
|
||||
static_assert(std::same_as<decltype(i), const int&&>);
|
||||
assert(i == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr E& error() & noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
template <class T>
|
||||
concept ErrorNoexcept =
|
||||
requires(T& t) {
|
||||
{ t.error() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!ErrorNoexcept<int>);
|
||||
static_assert(ErrorNoexcept<std::unexpected<int>>);
|
||||
|
||||
constexpr bool test() {
|
||||
std::unexpected<int> unex(5);
|
||||
decltype(auto) i = unex.error();
|
||||
static_assert(std::same_as<decltype(i), int&>);
|
||||
assert(i == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr E&& error() && noexcept;
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
template <class T>
|
||||
concept ErrorNoexcept =
|
||||
requires(T&& t) {
|
||||
{ std::move(t).error() } noexcept;
|
||||
};
|
||||
|
||||
static_assert(!ErrorNoexcept<int>);
|
||||
static_assert(ErrorNoexcept<std::unexpected<int>>);
|
||||
|
||||
constexpr bool test() {
|
||||
std::unexpected<int> unex(5);
|
||||
decltype(auto) i = std::move(unex).error();
|
||||
static_assert(std::same_as<decltype(i), int&&>);
|
||||
assert(i == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)));
|
||||
//
|
||||
// Constraints: is_swappable_v<E> is true.
|
||||
//
|
||||
// Effects: Equivalent to x.swap(y).
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
// test noexcept
|
||||
struct NoexceptSwap {
|
||||
friend void swap(NoexceptSwap&, NoexceptSwap&) noexcept;
|
||||
};
|
||||
|
||||
struct MayThrowSwap {
|
||||
friend void swap(MayThrowSwap&, MayThrowSwap&);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
concept ADLSwapNoexcept =
|
||||
requires(T& t1, T& t2) {
|
||||
{ swap(t1, t2) } noexcept;
|
||||
};
|
||||
|
||||
static_assert(ADLSwapNoexcept<std::unexpected<NoexceptSwap>>);
|
||||
static_assert(!ADLSwapNoexcept<std::unexpected<MayThrowSwap>>);
|
||||
|
||||
// test constraint
|
||||
struct NonSwappable {
|
||||
NonSwappable& operator=(const NonSwappable&) = delete;
|
||||
};
|
||||
|
||||
static_assert(std::is_swappable_v<std::unexpected<int>>);
|
||||
static_assert(std::is_swappable_v<std::unexpected<MayThrowSwap>>);
|
||||
static_assert(!std::is_swappable_v<std::unexpected<NonSwappable>>);
|
||||
|
||||
struct ADLSwap {
|
||||
constexpr ADLSwap(int ii) : i(ii) {}
|
||||
ADLSwap& operator=(const ADLSwap&) = delete;
|
||||
int i;
|
||||
constexpr friend void swap(ADLSwap& x, ADLSwap& y) { std::swap(x.i, y.i); }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
std::unexpected<ADLSwap> unex1(5);
|
||||
std::unexpected<ADLSwap> unex2(6);
|
||||
swap(unex1, unex2);
|
||||
assert(unex1.error().i == 6);
|
||||
assert(unex2.error().i == 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// constexpr void swap(unexpected& other) noexcept(is_nothrow_swappable_v<E>);
|
||||
//
|
||||
// Mandates: is_swappable_v<E> is true.
|
||||
//
|
||||
// Effects: Equivalent to: using std::swap; swap(unex, other.unex);
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <utility>
|
||||
|
||||
// test noexcept
|
||||
struct NoexceptSwap {
|
||||
friend void swap(NoexceptSwap&, NoexceptSwap&) noexcept;
|
||||
};
|
||||
|
||||
struct MayThrowSwap {
|
||||
friend void swap(MayThrowSwap&, MayThrowSwap&);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
concept MemberSwapNoexcept =
|
||||
requires(T& t1, T& t2) {
|
||||
{ t1.swap(t2) } noexcept;
|
||||
};
|
||||
|
||||
static_assert(MemberSwapNoexcept<std::unexpected<NoexceptSwap>>);
|
||||
static_assert(!MemberSwapNoexcept<std::unexpected<MayThrowSwap>>);
|
||||
|
||||
struct ADLSwap {
|
||||
constexpr ADLSwap(int ii) : i(ii) {}
|
||||
ADLSwap& operator=(const ADLSwap&) = delete;
|
||||
int i;
|
||||
constexpr friend void swap(ADLSwap& x, ADLSwap& y) { std::swap(x.i, y.i); }
|
||||
};
|
||||
|
||||
constexpr bool test() {
|
||||
// using std::swap;
|
||||
{
|
||||
std::unexpected<int> unex1(5);
|
||||
std::unexpected<int> unex2(6);
|
||||
unex1.swap(unex2);
|
||||
assert(unex1.error() == 6);
|
||||
assert(unex2.error() == 5);
|
||||
}
|
||||
|
||||
// adl swap
|
||||
{
|
||||
std::unexpected<ADLSwap> unex1(5);
|
||||
std::unexpected<ADLSwap> unex2(6);
|
||||
unex1.swap(unex2);
|
||||
assert(unex1.error().i == 6);
|
||||
assert(unex2.error().i == 5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// constexpr expected& operator=(const expected& rhs);
|
||||
//
|
||||
// Effects:
|
||||
// - If this->has_value() && rhs.has_value() is true, no effects.
|
||||
// - Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false;
|
||||
// - Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
|
||||
// - Otherwise, equivalent to unex = rhs.error().
|
||||
//
|
||||
// Returns: *this.
|
||||
//
|
||||
// Remarks: This operator is defined as deleted unless is_copy_assignable_v<E> is true and is_copy_constructible_v<E> is true.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotCopyConstructible {
|
||||
NotCopyConstructible(const NotCopyConstructible&) = delete;
|
||||
NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
|
||||
};
|
||||
|
||||
struct NotCopyAssignable {
|
||||
NotCopyAssignable(const NotCopyAssignable&) = default;
|
||||
NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_copy_assignable_v<std::expected<void, int>>);
|
||||
|
||||
// !is_copy_assignable_v<E>
|
||||
static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyAssignable>>);
|
||||
|
||||
// !is_copy_constructible_v<E>
|
||||
static_assert(!std::is_copy_assignable_v<std::expected<void, NotCopyConstructible>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// If this->has_value() && rhs.has_value() is true, no effects.
|
||||
{
|
||||
std::expected<void, int> e1;
|
||||
std::expected<void, int> e2;
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, int>&>);
|
||||
assert(&x == &e1);
|
||||
assert(e1.has_value());
|
||||
}
|
||||
|
||||
// Otherwise, if this->has_value() is true, equivalent to: construct_at(addressof(unex), rhs.unex); has_val = false;
|
||||
{
|
||||
Traced::state state{};
|
||||
std::expected<void, Traced> e1;
|
||||
std::expected<void, Traced> e2(std::unexpect, state, 5);
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 5);
|
||||
|
||||
assert(state.copyCtorCalled);
|
||||
}
|
||||
|
||||
// Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
|
||||
{
|
||||
Traced::state state{};
|
||||
std::expected<void, Traced> e1(std::unexpect, state, 5);
|
||||
std::expected<void, Traced> e2;
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
assert(e1.has_value());
|
||||
|
||||
assert(state.dtorCalled);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to unex = rhs.error().
|
||||
{
|
||||
Traced::state state{};
|
||||
std::expected<void, Traced> e1(std::unexpect, state, 5);
|
||||
std::expected<void, Traced> e2(std::unexpect, state, 10);
|
||||
decltype(auto) x = (e1 = e2);
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
|
||||
assert(state.copyAssignCalled);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
std::expected<void, ThrowOnCopyConstruct> e1(std::in_place);
|
||||
std::expected<void, ThrowOnCopyConstruct> e2(std::unexpect);
|
||||
try {
|
||||
e1 = e2;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// constexpr expected& operator=(expected&& rhs) noexcept(see below);
|
||||
//
|
||||
// Effects:
|
||||
// - If this->has_value() && rhs.has_value() is true, no effects.
|
||||
// - Otherwise, if this->has_value() is true, equivalent to:
|
||||
// construct_at(addressof(unex), std::move(rhs.unex));
|
||||
// has_val = false;
|
||||
// - Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
|
||||
// - Otherwise, equivalent to unex = std::move(rhs.error()).
|
||||
//
|
||||
// Returns: *this.
|
||||
//
|
||||
// Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>.
|
||||
//
|
||||
// This operator is defined as deleted unless is_move_constructible_v<E> is true and is_move_assignable_v<E> is true.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotMoveConstructible {
|
||||
NotMoveConstructible(NotMoveConstructible&&) = delete;
|
||||
NotMoveConstructible& operator=(NotMoveConstructible&&) = default;
|
||||
};
|
||||
|
||||
struct NotMoveAssignable {
|
||||
NotMoveAssignable(NotMoveAssignable&&) = default;
|
||||
NotMoveAssignable& operator=(NotMoveAssignable&&) = delete;
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_move_assignable_v<std::expected<void, int>>);
|
||||
|
||||
// !is_move_assignable_v<E>
|
||||
static_assert(!std::is_move_assignable_v<std::expected<void, NotMoveAssignable>>);
|
||||
|
||||
// !is_move_constructible_v<E>
|
||||
static_assert(!std::is_move_assignable_v<std::expected<void, NotMoveConstructible>>);
|
||||
|
||||
// Test noexcept
|
||||
struct MoveCtorMayThrow {
|
||||
MoveCtorMayThrow(MoveCtorMayThrow&&) noexcept(false) {}
|
||||
MoveCtorMayThrow& operator=(MoveCtorMayThrow&&) noexcept = default;
|
||||
};
|
||||
|
||||
struct MoveAssignMayThrow {
|
||||
MoveAssignMayThrow(MoveAssignMayThrow&&) noexcept = default;
|
||||
MoveAssignMayThrow& operator=(MoveAssignMayThrow&&) noexcept(false) { return *this; }
|
||||
};
|
||||
|
||||
// Test noexcept
|
||||
static_assert(std::is_nothrow_move_assignable_v<std::expected<void, int>>);
|
||||
|
||||
// !is_nothrow_move_assignable_v<E>
|
||||
static_assert(!std::is_nothrow_move_assignable_v<std::expected<void, MoveAssignMayThrow>>);
|
||||
|
||||
// !is_nothrow_move_constructible_v<E>
|
||||
static_assert(!std::is_nothrow_move_assignable_v<std::expected<void, MoveCtorMayThrow>>);
|
||||
|
||||
constexpr bool test() {
|
||||
// If this->has_value() && rhs.has_value() is true, no effects.
|
||||
{
|
||||
std::expected<void, int> e1;
|
||||
std::expected<void, int> e2;
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, int>&>);
|
||||
assert(&x == &e1);
|
||||
assert(e1.has_value());
|
||||
}
|
||||
|
||||
// Otherwise, if this->has_value() is true, equivalent to:
|
||||
// construct_at(addressof(unex), std::move(rhs.unex));
|
||||
// has_val = false;
|
||||
{
|
||||
Traced::state state{};
|
||||
std::expected<void, Traced> e1;
|
||||
std::expected<void, Traced> e2(std::unexpect, state, 5);
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 5);
|
||||
|
||||
assert(state.moveCtorCalled);
|
||||
}
|
||||
|
||||
// Otherwise, if rhs.has_value() is true, destroys unex and sets has_val to true.
|
||||
{
|
||||
Traced::state state{};
|
||||
std::expected<void, Traced> e1(std::unexpect, state, 5);
|
||||
std::expected<void, Traced> e2;
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
assert(e1.has_value());
|
||||
|
||||
assert(state.dtorCalled);
|
||||
}
|
||||
|
||||
// Otherwise, equivalent to unex = rhs.error().
|
||||
{
|
||||
Traced::state state{};
|
||||
std::expected<void, Traced> e1(std::unexpect, state, 5);
|
||||
std::expected<void, Traced> e2(std::unexpect, state, 10);
|
||||
decltype(auto) x = (e1 = std::move(e2));
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e1);
|
||||
assert(!e1.has_value());
|
||||
assert(e1.error().data_ == 10);
|
||||
|
||||
assert(state.moveAssignCalled);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
std::expected<void, ThrowOnMoveConstruct> e1(std::in_place);
|
||||
std::expected<void, ThrowOnMoveConstruct> e2(std::unexpect);
|
||||
try {
|
||||
e1 = std::move(e2);
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
|
||||
// Older Clangs do not support the C++20 feature to constrain destructors
|
||||
// XFAIL: clang-14, apple-clang-14
|
||||
|
||||
// template<class G>
|
||||
// constexpr expected& operator=(const unexpected<G>& e);
|
||||
//
|
||||
// Let GF be const G&
|
||||
//
|
||||
// Constraints: is_constructible_v<E, GF> is true and is_assignable_v<E&, GF> is true.
|
||||
//
|
||||
// Effects:
|
||||
// - If has_value() is true, equivalent to:
|
||||
// construct_at(addressof(unex), std::forward<GF>(e.error()));
|
||||
// has_val = false;
|
||||
// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
|
||||
//
|
||||
// Returns: *this.
|
||||
|
||||
#include <cassert>
|
||||
#include <concepts>
|
||||
#include <expected>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
struct NotCopyConstructible {
|
||||
NotCopyConstructible(const NotCopyConstructible&) = delete;
|
||||
NotCopyConstructible& operator=(const NotCopyConstructible&) = default;
|
||||
};
|
||||
|
||||
struct NotCopyAssignable {
|
||||
NotCopyAssignable(const NotCopyAssignable&) = default;
|
||||
NotCopyAssignable& operator=(const NotCopyAssignable&) = delete;
|
||||
};
|
||||
|
||||
struct MoveMayThrow {
|
||||
MoveMayThrow(MoveMayThrow const&) = default;
|
||||
MoveMayThrow& operator=(const MoveMayThrow&) = default;
|
||||
MoveMayThrow(MoveMayThrow&&) noexcept(false) {}
|
||||
MoveMayThrow& operator=(MoveMayThrow&&) noexcept(false) { return *this; }
|
||||
};
|
||||
|
||||
// Test constraints
|
||||
static_assert(std::is_assignable_v<std::expected<void, int>&, const std::unexpected<int>&>);
|
||||
|
||||
// !is_constructible_v<E, GF>
|
||||
static_assert(
|
||||
!std::is_assignable_v<std::expected<void, NotCopyConstructible>&, const std::unexpected<NotCopyConstructible>&>);
|
||||
|
||||
// !is_assignable_v<E&, GF>
|
||||
static_assert(
|
||||
!std::is_assignable_v<std::expected<void, NotCopyAssignable>&, const std::unexpected<NotCopyAssignable>&>);
|
||||
|
||||
constexpr bool test() {
|
||||
// - If has_value() is true, equivalent to:
|
||||
// construct_at(addressof(unex), std::forward<GF>(e.error()));
|
||||
// has_val = false;
|
||||
{
|
||||
Traced::state state{};
|
||||
std::expected<void, Traced> e;
|
||||
std::unexpected<Traced> un(std::in_place, state, 5);
|
||||
decltype(auto) x = (e = un);
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e);
|
||||
assert(!e.has_value());
|
||||
assert(e.error().data_ == 5);
|
||||
|
||||
assert(state.copyCtorCalled);
|
||||
}
|
||||
|
||||
// - Otherwise, equivalent to: unex = std::forward<GF>(e.error());
|
||||
{
|
||||
Traced::state state1{};
|
||||
Traced::state state2{};
|
||||
std::expected<void, Traced> e(std::unexpect, state1, 5);
|
||||
std::unexpected<Traced> un(std::in_place, state2, 10);
|
||||
decltype(auto) x = (e = un);
|
||||
static_assert(std::same_as<decltype(x), std::expected<void, Traced>&>);
|
||||
assert(&x == &e);
|
||||
assert(!e.has_value());
|
||||
assert(e.error().data_ == 10);
|
||||
|
||||
assert(state1.copyAssignCalled);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void testException() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
std::expected<void, ThrowOnCopyConstruct> e1(std::in_place);
|
||||
std::unexpected<ThrowOnCopyConstruct> un(std::in_place);
|
||||
try {
|
||||
e1 = un;
|
||||
assert(false);
|
||||
} catch (Except) {
|
||||
assert(e1.has_value());
|
||||
}
|
||||
#endif // TEST_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
testException();
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user