[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:
Hui Xie 2022-11-04 11:42:42 +00:00 committed by Hui
parent e6b9fc4c8b
commit e356f681f6
125 changed files with 10421 additions and 425 deletions

View File

@ -318,6 +318,8 @@ Status
------------------------------------------------- -----------------
``__cpp_lib_constexpr_typeinfo`` *unimplemented*
------------------------------------------------- -----------------
``__cpp_lib_expected`` ``202202L``
------------------------------------------------- -----------------
``__cpp_lib_forward_like`` ``202207L``
------------------------------------------------- -----------------
``__cpp_lib_invoke_r`` *unimplemented*

View File

@ -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.

View File

@ -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.

View File

@ -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

View 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

View 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

View 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

View 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

View File

@ -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

View File

@ -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)

View File

@ -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
View 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

View File

@ -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" ] },

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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)

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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'}}

View File

@ -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

View File

@ -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

1 algorithm atomic
202 exception type_traits
203 exception version
204 execution version
205 expected cstddef
206 expected cstdlib
207 expected exception
208 expected initializer_list
209 expected new
210 expected type_traits
211 expected version
212 experimental/algorithm algorithm
213 experimental/algorithm cstddef
214 experimental/algorithm type_traits

View File

@ -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

1 algorithm atomic
202 exception type_traits
203 exception version
204 execution version
205 expected cstddef
206 expected cstdlib
207 expected exception
208 expected initializer_list
209 expected new
210 expected type_traits
211 expected version
212 experimental/algorithm algorithm
213 experimental/algorithm cstddef
214 experimental/algorithm type_traits

View File

@ -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

1 algorithm atomic
202 exception type_traits
203 exception version
204 execution version
205 expected cstddef
206 expected cstdlib
207 expected exception
208 expected initializer_list
209 expected new
210 expected type_traits
211 expected version
212 experimental/algorithm algorithm
213 experimental/algorithm cstddef
214 experimental/algorithm type_traits

View File

@ -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

1 algorithm atomic
202 exception type_traits
203 exception version
204 execution version
205 expected cstddef
206 expected cstdlib
207 expected exception
208 expected initializer_list
209 expected new
210 expected type_traits
211 expected version
212 experimental/algorithm algorithm
213 experimental/algorithm cstddef
214 experimental/algorithm type_traits

View File

@ -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

1 algorithm atomic
214 exception type_traits
215 exception version
216 execution version
217 expected cstddef
218 expected cstdlib
219 expected exception
220 expected initializer_list
221 expected new
222 expected type_traits
223 expected version
224 experimental/algorithm algorithm
225 experimental/algorithm cstddef
226 experimental/algorithm type_traits

View File

@ -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

1 algorithm bit
168 exception type_traits
169 exception version
170 execution version
171 expected cstddef
172 expected cstdlib
173 expected exception
174 expected initializer_list
175 expected new
176 expected type_traits
177 expected version
178 experimental/algorithm algorithm
179 experimental/algorithm cstddef
180 experimental/algorithm type_traits

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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>>);

View File

@ -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}}
}
}

View File

@ -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]}}

View File

@ -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>>);

View File

@ -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}}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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>>);

View 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

View 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;
}

View File

@ -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

View File

@ -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"

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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>>);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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>>);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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