Skip to content
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7da7d62
Start work on pfn::optional, all is TODO now
Bronek Mar 4, 2026
7c4277a
Merge branch 'main' into bronek/optional_polyfill
Bronek Apr 23, 2026
46b9359
Readability
Bronek Apr 23, 2026
986fbb7
Merge branch 'main' into bronek/optional_polyfill
Bronek Jun 30, 2026
445bfca
Merge branch 'main' into bronek/optional_polyfill
Bronek Jun 30, 2026
a435cd3
Make pfn/expected detail names expected-specific
Bronek Jun 30, 2026
67ee692
Add _optional_union_t storage for pfn::optional
Bronek Jun 30, 2026
5a7af01
Add _optional_base and implement pfn::optional constructors and destr…
Bronek Jun 30, 2026
e76a5d1
Add pfn::optional constructor and destructor tests
Bronek Jun 30, 2026
a33ac26
Fix over-gated noexcept assertion in optional's move-only test
Bronek Jul 1, 2026
1f37d6c
Add optional_validation.cpp to validate pfn::optional against std::op…
Bronek Jul 1, 2026
38ae702
Implement pfn::optional assignment, emplace and observers
Bronek Jul 1, 2026
25df9a5
Implement pfn::optional<T&> assignment, emplace and observers
Bronek Jul 1, 2026
f138753
Implement pfn::optional converting constructors and assignment
Bronek Jul 1, 2026
b986b57
Update CLAUDE.md: C++20 status, feature+tests convention, streamlining
Bronek Jul 1, 2026
5a05d33
Add pfn::optional to CONTRIBUTING's pfn description
Bronek Jul 1, 2026
878ed20
Merge branch 'main' into bronek/optional_polyfill
Bronek Jul 1, 2026
c682d5a
Enforce valid contained type for optional [optional.optional.general]
Bronek Jul 2, 2026
02c8108
Implement pfn::optional value and value_or observers
Bronek Jul 2, 2026
7b210b5
Implement pfn::optional<T&> converting constructors and observers
Bronek Jul 2, 2026
02cd626
Fix optional accessor tests for MSVC and gcc on macOS
Bronek Jul 2, 2026
9203e30
Spell _convert_ref_init_val's reference binding via static_cast for MSVC
Bronek Jul 2, 2026
4769dba
Declare defaulted trivial copy/move constructors noexcept
Bronek Jul 2, 2026
6996ac8
Implement pfn::optional swap and reset
Bronek Jul 2, 2026
55c1a08
Implement pfn::optional comparisons, make_optional and hash
Bronek Jul 3, 2026
e90048c
Gate optional <=> validation tests on __cpp_lib_three_way_comparison
Bronek Jul 3, 2026
b78c8ef
Exercise optional relops' disengaged branches at runtime
Bronek Jul 3, 2026
fa04cc7
Implement pfn::optional monadic operations
Bronek Jul 3, 2026
73d00b5
Update copyright year
Bronek Jul 3, 2026
4015dc7
Spell optional's value() with if-throw for MSVC constexpr
Bronek Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This is for working *on* libfn; to *use* the library, see the [README](README.md

## Development environment

Building and testing libfn needs a C++20 toolchain (with one exception). `pfn` polyfills the C++23 standard-library utilities that `fn` builds on (`pfn::expected`, `pfn::invoke_r`, `pfn::unreachable`). The minimum supported compilers are [gcc 12][gcc-standard-support] and [clang 16][clang-standard-support]; if your OS does not ship one recent enough, use the [devcontainer] or [Nix][nix] (see [nix/README.md][nixmd]). You may also use Apple Clang 16.0 or Microsoft Visual Studio 2022 or newer.
Building and testing libfn needs a C++20 toolchain (with one exception). `pfn` polyfills C++23/26 standard-library utilities (`pfn::expected`, `pfn::optional`, `pfn::invoke_r`, `pfn::unreachable`); `fn` builds on `pfn` rather than the newer standard library. The minimum supported compilers are [gcc 12][gcc-standard-support] and [clang 16][clang-standard-support]; if your OS does not ship one recent enough, use the [devcontainer] or [Nix][nix] (see [nix/README.md][nixmd]). You may also use Apple Clang 16.0 or Microsoft Visual Studio 2022 or newer.

When working with `tests/pfn/expected.cpp` you will need a C++23 compiler, in order to enable the `VALIDATE_CXX23` option for `expected_validation.cpp` tests.

Expand Down
32 changes: 16 additions & 16 deletions include/fn/expected.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ struct expected_policy {
// Storage layer for ::fn::expected. Inherits the standard-conformant base from
// pfn, then hides the four monadic static helpers with sum-widening variants
// that materialise their result via `expected_policy::template type<U, G>`.
template <typename T, typename E> struct _storage : ::pfn::detail::_storage<T, E, expected_policy> {
using _pfn_base = ::pfn::detail::_storage<T, E, expected_policy>;
template <typename T, typename E> struct _expected_base : ::pfn::detail::_expected_base<T, E, expected_policy> {
using _pfn_base = ::pfn::detail::_expected_base<T, E, expected_policy>;
using _pfn_base::_pfn_base;

// and_then, non-void value type
Expand Down Expand Up @@ -248,18 +248,18 @@ template <typename T, typename E> struct _storage : ::pfn::detail::_storage<T, E
} // namespace detail

// Primary template - non-void value type
template <typename T, typename Err> struct expected : private detail::_storage<T, Err> {
using _base = detail::_storage<T, Err>;
template <typename T, typename Err> struct expected : private detail::_expected_base<T, Err> {
using _base = detail::_expected_base<T, Err>;
using value_type = T;
using error_type = Err;
using unexpected_type = ::pfn::unexpected<Err>;
static_assert(not ::std::is_same_v<value_type, ::fn::sum<>>);

template <class U> using rebind = expected<U, error_type>;

// Allow sibling _storage instantiations to downcast into the private base.
template <class, class, class> friend struct ::pfn::detail::_storage;
template <class, class> friend struct ::fn::detail::_storage;
// Allow sibling _expected_base instantiations to downcast into the private base.
template <class, class, class> friend struct ::pfn::detail::_expected_base;
template <class, class> friend struct ::fn::detail::_expected_base;

// Constructors. Explicit forwarders to the base mirror pfn::expected.
constexpr expected() noexcept(::std::is_nothrow_default_constructible_v<T>)
Expand Down Expand Up @@ -414,7 +414,7 @@ template <typename T, typename Err> struct expected : private detail::_storage<T
return *this;
}

// Observers inherited from _storage
// Observers inherited from _expected_base
using _base::operator*;
using _base::operator->;
using _base::operator bool;
Expand All @@ -425,10 +425,10 @@ template <typename T, typename Err> struct expected : private detail::_storage<T
using _base::value;
using _base::value_or;

// Emplace inherited from _storage
// Emplace inherited from _expected_base
using _base::emplace;

// Swap; body delegates to _storage helper
// Swap; body delegates to _expected_base helper
constexpr void
swap(expected &rhs) noexcept(::std::is_nothrow_move_constructible_v<T> && ::std::is_nothrow_swappable_v<T>
&& ::std::is_nothrow_move_constructible_v<Err> && ::std::is_nothrow_swappable_v<Err>)
Expand All @@ -439,7 +439,7 @@ template <typename T, typename Err> struct expected : private detail::_storage<T
this->_swap_with(rhs);
}

// Monadic operations. Bodies delegate to _storage static helpers, which perform sum-widening.
// Monadic operations. Bodies delegate to _expected_base static helpers, which perform sum-widening.
template <class F>
constexpr auto and_then(F &&f) & //
noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
Expand Down Expand Up @@ -636,16 +636,16 @@ template <typename T, typename Err> struct expected : private detail::_storage<T
}
};

template <typename Err> struct expected<void, Err> : private detail::_storage<void, Err> {
using _base = detail::_storage<void, Err>;
template <typename Err> struct expected<void, Err> : private detail::_expected_base<void, Err> {
using _base = detail::_expected_base<void, Err>;
using value_type = void;
using error_type = Err;
using unexpected_type = ::pfn::unexpected<Err>;

template <class U> using rebind = expected<U, error_type>;

template <class, class, class> friend struct ::pfn::detail::_storage;
template <class, class> friend struct ::fn::detail::_storage;
template <class, class, class> friend struct ::pfn::detail::_expected_base;
template <class, class> friend struct ::fn::detail::_expected_base;

constexpr expected() noexcept : _base(::std::in_place) {}

Expand Down Expand Up @@ -766,7 +766,7 @@ template <typename Err> struct expected<void, Err> : private detail::_storage<vo
using _base::has_value;
using _base::value;

// Monadic operations. Bodies delegate to _storage static helpers, which perform sum-widening.
// Monadic operations. Bodies delegate to _expected_base static helpers, which perform sum-widening.
template <class F>
constexpr auto and_then(F &&f) & //
noexcept(noexcept(_base::_and_then(*this, FWD(f)))) // extension
Expand Down
Loading
Loading