[PATCH gcc/* v3 1/2] gcc: backport std::{optional, expected} from libstdc++ into C++14

Arsen Arsenović aarsenovic@baylibre.com
Sat Sep 5 13:07:41 GMT 2026


This patch adds an implementation of std::optional and std::expected
compatible with C++14.

The std::optional implementation was mostly backported mechanically, via
the Elisp script attached below.  Further hand-massaging was needed to
clean up conditionals and includes and such.  Same goes for most of the
bits headers, though some differ substantially to their originals or do
not correspond to an original (stl_construct comes to mind, and
obviously extras/more_type_traits).

The std::expected implementation initially started out as such, but it
turned out that the "hand-massaging" part ends up being a massive
restructuring, so I tossed it and started afresh.

gcc::expected is a full implementation of [expected], and passes both
Sy's testsuite (that of tl::expected), and the libstdc++
testsuite (minus some erroneous and non-applicable tests from both, such
as the synopsis test, which obviously will fail).

The latter was ran by replacing the implementation in
include/std/expected with:

  #define gccbackport_assert(x) __glibcxx_assert(x)
  #define GCC_BACKPORT_WANT_EXCEPTIONS
  #include "/home/arsen/gcc/gcc/gcc/stdbackport/expected"

  namespace std
  {
    using gcc::unexpected;
    using gcc::bad_expected_access;
    using gcc::unexpect_t;
    using gcc::unexpect;
    using gcc::expected;
  }

Similarly, I did the same thing to std::optional:

  #define gccbackport_assert(x) __glibcxx_assert(x)
  #define GCC_BACKPORT_WANT_EXCEPTIONS
  #include "/home/arsen/gcc/gcc/gcc/stdbackport/optional"

  namespace std
  {
    using gcc::optional;
    using gcc::make_optional;
    using gcc::bad_optional_access;
    using gcc::nullopt_t;
    using gcc::nullopt;
  }

This one had more fails, because I cut out ranges and formatting support
and some libstdc++ specifics, but those fails are obviously
non-applicable anyway.

Neither of these implementations rely on reserved identifiers any
longer, so they should work on any compiler.

On GCC_BACKPORT_WANT_EXCEPTIONS: as mentioned, there was use in having
the backports be a as complete an implementation for the testsuite as
possible, but I wanted to avoid the <exception> dependency.  That can't
necessarily be done using __cpp_exceptions because that FTM is not
guaranteed to exist.

I decided that, since exceptions are only needed for running tests as a
hack, they might as well be dropped by default, even if __cpp_exceptions
and thus we avoid the otherwise-redundant <exception> dependency.

For similar reasons, I also kept the spaceship operators for <optional>.

It may be worth dropping them to prevent bitrot and accidental use.

These versions are "frozen in time" at C++26-ish, as the Rust FE used
some features from [optional.monadic].  This may mean it's harder to
drop them later, but we can revisit that problem somewhere down the
line.

Though, do note that I preserved the usages of [[nodiscard]], which is
in C++17+.  I think this should be fine because we only build stage1
with -std=c++14, and stage1 is built without -Werror, so the diagnostics
emitted for the use of [[nodiscard]] are harmless (whereas [[nodiscard]]
is quite useful).

The "backporting" script follows:

;; -*- lexical-binding: t; -*-

(require 'c-ts-mode)
(require 'c++-ts-mode)
(eval-when-compile
  (require 'llama))

(defvar arsen/std-identifiers
  (let ((hash (make-hash-table :test #'equal)))
    (dolist
	(i
	 ;; Generated by hacking the uglification plugin to dump the whitelist
	 ;; at the end of the TU.
	 ;; List removed because it contains ~300 identifiers.
	 )
      (puthash i t hash))
    (remhash "unexpected" hash)
    ;; Needs to ADL.
    (remhash "swap" hash)
    hash)
  "All the identifiers present in a few headers in std:: per
uglification_plugin.  Definitely over-eager, but whatever.")

(defun arsen/ts-find-parent-declarator (n)
  "Find parent of node N such that N is part of its name."
  (while (and n
	      (not (string= "declarator" (treesit-node-field-name n)))
	      (not (and (string= "name" (treesit-node-field-name n))
			(string= "alias_declaration"
				 (treesit-node-type
				  (treesit-node-parent n)))))
	      (not (and (string= "name" (treesit-node-field-name n))
			(string= "class_specifier"
				 (treesit-node-type
				  (treesit-node-parent n))))))
    (let ((parent (treesit-node-parent n)))
      (cond
       ;; As a special case, if PARENT is an init_declarator, and we're its
       ;; value field, terminate the search.
       ;;
       ;; In reality, we should be having a list of nodes that can appear in a
       ;; declarator name, rather than special-casing ways we can escape, but
       ;; whatever.
       ((and (member (treesit-node-type parent) '("init_declarator"
						  "requires_clause"))
	     (string= (treesit-node-field-name n) "value"))
	(setq n nil))
       ;; Likewise for some of the conditioned keywords.
       ((member (treesit-node-type parent) '("noexcept"
					     "parameter_declaration"
					     "explicit_function_specifier"))
	(setq n nil))
       (t
	(setq n parent))))
    )

  (treesit-node-parent n))

(defun arsen/delibrarize ()
  "Convert the header in the current buffer into a version usable outside of
the standard library implementation, in a new buffer."
  (interactive)
  (let ((out (get-buffer-create "*delibrarized*"))
	;; We never want case folding for this.
	(case-fold-search nil)
	edits)
    ;; Duplicate the buffer
    (insert-into-buffer out (point-min) (point-max))

    ;; Enter it.
    (switch-to-buffer out)
    ;; Get the parser going.
    (c++-ts-mode)

    ;; First, let's deal with the header guard.  Presuming it is the first
    ;; #ifndef, find it and replace it.
    (save-match-data
      (goto-char (point-min))
      (when (search-forward "#ifndef" nil t)
	;; Presume next token is the guard variable.
	(forward-sexp)
	(let ((end (point))
	      guard)
	  (backward-sexp)
	  (setq guard (buffer-substring-no-properties (point) end))

	  ;; Do the replacement.
	  (goto-char (point-min))
	  (save-match-data
	    (while (search-forward guard nil t)
	      (replace-match "GCC_BACKPORT\\&" t))))))

    ;; Let's delete the SYSHDR pragma next.
    (save-match-data
      (goto-char (point-min))
      (if (search-forward "system_header" nil t)
	  (delete-region
	   (progn (backward-paragraph) (point))
	   (progn (forward-paragraph) (point)))))

    ;; And the bits/version.h use.  Rest of the cleanup of that remains to be
    ;; done by hand.
    (goto-char (point-min))
    (save-match-data
      (if (search-forward "bits/version.h" nil t)
	  (delete-region
	   (progn (backward-paragraph) (point))
	   (progn (forward-paragraph) (point)))))

    ;; And the versioning namespace use.  And std::
    (delete-matching-lines
     "_GLIBCXX_\\(BEGIN\\|END\\)_NAMESPACE_VERSION"
     (point-min) (point-max))
    (goto-char (point-min))
    (save-match-data
      (while (re-search-forward "namespace std.*" nil t)
	(replace-match "namespace gcc" t)))

    ;; And resolve the _GLIBCXXvv_KEYWORD keywords.
    (save-match-data
      (goto-char (point-min))
      (while (re-search-forward
	      "_GLIBCXX\\([[:digit:]]+\\)_\\([A-Z]+\\)\\([[:blank:]]*\\)"
	      nil t)
	(let ((version (string-to-number (match-string-no-properties 1)))
	      (keyword (downcase (match-string-no-properties 2)))
	      (space (match-string-no-properties 3)))
	  (if (or (<= version 14) (string= keyword "constexpr"))
	      (replace-match (concat keyword space) t)
	    (replace-match "")))
	;; If the line is now empty, clean it up.
	(beginning-of-line)
	(when (looking-at (rx (* blank) eol))
	  (kill-line))))

    ;; And replace __glibcxx_assert.
    (save-match-data
      (goto-char (point-min))
      (while (re-search-forward (rx bow "__glibcxx_assert" eow) nil t)
	(replace-match "gcc_assert")))

    ;; Now for the fun stuff.  Cleaning up identifiers.
    ;; This needs to happen in two passes; in one, we collect edits, and in the
    ;; next, we perform them.  This is because the tree-sitter tree goes
    ;; out-of-date on edit and needs replacing.
    (setq edits nil)
    (cl-flet* ((queue-edit (start end newtext)
		 (cl-assert (<= start end))
		 (cl-check-type start number-or-marker)
		 (cl-check-type end number-or-marker)
		 (cl-check-type newtext string)
		 (push `(,start ,end ,newtext) edits))
	       (queue-replace (node newtext)
		 (queue-edit (treesit-node-start node)
			     (treesit-node-end node)
			     newtext)))
      (pcase-dolist (`(_ . ,(and i (app treesit-node-text itext)))
		     ( treesit-query-capture (treesit-buffer-root-node)
		       '((([(identifier)
			    (type_identifier)
			    (field_identifier)
			    (statement_identifier)] @identifier)))))
	;; Makes it easier to see what we're looking at in Edebug.
	(goto-char (treesit-node-start i))

	(cond
	 ((= (treesit-node-start i) (treesit-node-end i))
	  ;; Skip empty nodes.
	  nil)
	 ((string-match-p "\\`\\(__cplusplus\\|__cpp_\\|__glibcxx_\\)" itext)
	  ;; Skip __cplusplus and __cpp_lib_... as those are standard, and
	  ;; __glibcxx since that surely needs hand-processing.
	  ;; Removing non-applicable of their clauses is to be done by hand.
	  nil)
	 ((string-match-p "\\`__builtin_" itext)
	  ;; Leave builtins in place.
	  nil)
	 ((string-match-p "\\`__has_builtin" itext)
	  ;; But replace has_builtin with a portable version.
	  (queue-replace i "gcc_backport_has_builtin"))
	 ((string-match-p "\\`remove_cvref" itext)
	  ;; Prefix remove_cvref with g_ for our backport.
	  (let ((s (treesit-node-start i)))
	    (queue-edit s s "g_")))
	 ((member itext '("__clang__" "__noreturn__" "__deprecated__"
			  "__gnu__" "__always_inline__"))
	  ;; Skip a variety of well-known identifiers.
	  nil)
	 ((string= itext "__addressof")
	  ;; We can use the standard one.
	  (if (looking-back "std::")
	      (queue-replace i "addressof")
	    (queue-replace i "std::addressof")))
	 ((string= itext "__invoke")
	  ;; Replace calls to __invoke with gcc::invoke.
	  (let ((invoke (treesit-parent-while
			 i "\\`\\(qualified_identifier\\|identifier\\)\\'")))
	    (queue-replace invoke "gcc::invoke")))
	 ((string= itext "invoke_result_t")
	  ;; Prefix invoke_result_t with g_
	  (let ((s (treesit-node-start i)))
	    (queue-edit s s "g_")))
	 (;; Add std:: to a bunch of standard names.
	  (and
	   (or (gethash itext arsen/std-identifiers)
	       ;; We can turn ..._v identifiers into their ::value variants,
	       (gethash (string-remove-suffix "_v" itext)
			arsen/std-identifiers))
	   ;; ... but not if they're in declarators or declarations,
	   (not (arsen/ts-find-parent-declarator i))
	   ;; ... or if they're a field,
	   (not (string= (treesit-node-type i) "field_identifier"))
	   ;; ... or if they're already qualified.
	   (not (looking-back "::[[:blank:]]*")))
	  (queue-edit (treesit-node-start i) (treesit-node-start i)
		      "std::"))
	 ((string-match-p "\\`__\\(and\\|not\\|or\\)_v?\\'" itext)
	  ;; Turn the helper conditional templates __COND[_v] into COND[_v].  A
	  ;; later pass below will turn COND_v<...> into COND_<...>::value.
	  ;;
	  ;; Make sure to only touch the underscores, not to overlap with that
	  ;; later pass.
	  (let ((s (treesit-node-start i)))
	    (queue-edit s (+ 2 s) "")))
	 ((string-match-p "\\`_[A-Z].*[a-z].*" itext)
	  ;; Move _Foo into the non-reserved identifier space as G_Foo, but
	  ;; don't catch macro names.
	  (queue-replace i (concat "G" itext)))
	 ((string-search "__" itext)
	  ;; Turn '__' into 'g_'
	  (let ((r (string-replace "__" "g_" itext))
		(s (treesit-node-start i))
		(e (treesit-node-end i)))
	    ;; Don't clash with the _v -> ...::value conversion rule below.
	    (when (string-suffix-p "_v" r)
	      (setq e (- e 2))
	      (setq r (string-remove-suffix "_v" r)))
	    (queue-edit s e r)))
	 ((string-equal itext "_GLIBCXX_THROW_OR_ABORT")
	  (queue-replace i "g_throw_or_abort"))
	 ))

      ;; Locate all ..._v type trait uses and replace them with ::value.
      (pcase-dolist (`(_ . ,(and i (app treesit-node-text itext)))
		     ( treesit-query-capture (treesit-buffer-root-node)
		       '([(template_type) (template_method)
			  (template_function)]
			 name: (_) @name)))
	(when-let*
	    ((_ (string-suffix-p "_v" itext))
	     ;; Find the parent.
	     (template-invoc (treesit-node-parent i))
	     (value-spot (treesit-node-end template-invoc)))
	  ;; Okay, got it.  Tack on ::value.
	  (queue-edit value-spot value-spot "::value")
	  ;; ... and erase the _v.  Be careful not to queue a replacement for
	  ;; the full identifier as that may create an overlap with the earlier
	  ;; passes.  Also, do not remove the underscore for and, not and or.
	  (let ((e (treesit-node-end i))
		(o (if (string-match-p "\\`__\\(and\\|not\\|or\\)_v\\'" itext)
		       1 2)))
	    (cl-assert (< (treesit-node-start i) (- e o)))
	    (queue-edit (- e o) e ""))))
      )

    ;; Check for overlaps, just in case.
    ;; First, ensure that the edits are in order (from end of file to start).
    (setq edits (sort edits (lambda (a b) (> (car a) (car b)))))
    ;; Then, for each consecutive pair, check them.
    (cl-loop for (start1 end1 r1) in edits
	     for (start2 end2 r2) in (cdr edits)
	     ;; These are now in descending order.  As in, ((3 4) (1 2))
	     unless (<= start2 end2 start1 end1)
	     do (debug "Bad replacement range"
		       (list start1 end1 r1)
		       (list start2 end2 r2)))

    ;; Do the replacements.
    (mapc (##apply #'replace-region-contents %1) edits)

    nil))

Bootstrap build tested w/ CXX='gcc-5.5.0 -std=c++14' on
x86_64-linux-gnu with the patches actually in use.

gcc/ChangeLog:

	* stdbackport/gbits/assert.h: New file.
	* stdbackport/gbits/enable_special_members.h: New file.
	* stdbackport/gbits/exception_defines.h: New file.
	* stdbackport/gbits/extras.h: New file.
	* stdbackport/gbits/functional_hash.h: New file.
	* stdbackport/gbits/inplace_tags.h: New file.
	* stdbackport/gbits/invoke.h: New file.
	* stdbackport/gbits/more_type_traits.h: New file.
	* stdbackport/gbits/optional_ref.h: New file.
	* stdbackport/gbits/stl_construct.h: New file.
	* stdbackport/expectedfwd: New file.
	* stdbackport/expected: New file.
	* stdbackport/optionalfwd: New file.
	* stdbackport/optional: New file.
---
 gcc/stdbackport/expected                      | 2361 +++++++++++++++++
 gcc/stdbackport/expectedfwd                   |   31 +
 gcc/stdbackport/gbits/assert.h                |   29 +
 gcc/stdbackport/gbits/check_system_h.h        |   31 +
 .../gbits/enable_special_members.h            |  310 +++
 gcc/stdbackport/gbits/exception_defines.h     |   53 +
 gcc/stdbackport/gbits/extras.h                |   56 +
 gcc/stdbackport/gbits/functional_hash.h       |   60 +
 gcc/stdbackport/gbits/inplace_tags.h          |   58 +
 gcc/stdbackport/gbits/invoke.h                |  132 +
 gcc/stdbackport/gbits/more_type_traits.h      |  614 +++++
 gcc/stdbackport/gbits/optional_ref.h          |  550 ++++
 gcc/stdbackport/gbits/stl_construct.h         |  162 ++
 gcc/stdbackport/optional                      | 1786 +++++++++++++
 gcc/stdbackport/optionalfwd                   |   36 +
 15 files changed, 6269 insertions(+)
 create mode 100644 gcc/stdbackport/expected
 create mode 100644 gcc/stdbackport/expectedfwd
 create mode 100644 gcc/stdbackport/gbits/assert.h
 create mode 100644 gcc/stdbackport/gbits/check_system_h.h
 create mode 100644 gcc/stdbackport/gbits/enable_special_members.h
 create mode 100644 gcc/stdbackport/gbits/exception_defines.h
 create mode 100644 gcc/stdbackport/gbits/extras.h
 create mode 100644 gcc/stdbackport/gbits/functional_hash.h
 create mode 100644 gcc/stdbackport/gbits/inplace_tags.h
 create mode 100644 gcc/stdbackport/gbits/invoke.h
 create mode 100644 gcc/stdbackport/gbits/more_type_traits.h
 create mode 100644 gcc/stdbackport/gbits/optional_ref.h
 create mode 100644 gcc/stdbackport/gbits/stl_construct.h
 create mode 100644 gcc/stdbackport/optional
 create mode 100644 gcc/stdbackport/optionalfwd

diff --git a/gcc/stdbackport/expected b/gcc/stdbackport/expected
new file mode 100644
index 000000000000..b14913456390
--- /dev/null
+++ b/gcc/stdbackport/expected
@@ -0,0 +1,2361 @@
+/* An <expected> for -*- C++ -*- 14.
+   Derived, in part, from the libstdc++ one, but mostly distinct.
+   Copyright (C) 2026 The GNU Toolchain Authors.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_EXPECTED
+#define GCC_EXPECTED 1
+
+#include <utility>
+#include <type_traits>
+#include <initializer_list>
+#include <memory>
+
+#include "gbits/assert.h"
+#include "gbits/enable_special_members.h"
+#include "gbits/exception_defines.h"
+#include "gbits/extras.h"
+#include "gbits/inplace_tags.h"
+#include "gbits/invoke.h"
+#include "gbits/more_type_traits.h"
+#include "gbits/stl_construct.h"
+
+#ifdef GCC_BACKPORT_WANT_EXCEPTIONS
+# include <exception>
+#endif
+
+#include "expectedfwd"
+
+namespace gcc
+{
+  // [expected]
+  template<typename E>
+  struct unexpected;
+
+  struct unexpect_t
+  {
+    explicit unexpect_t() = default;
+  };
+  static constexpr unexpect_t unexpect{};
+
+  template<typename T, typename E>
+  struct expected;
+
+  namespace detail { namespace exp
+  {
+    template<typename T>
+    struct is_unexpected : std::false_type {};
+
+    template<typename E>
+    struct is_unexpected<unexpected<E>> : std::true_type {};
+
+    template<typename T>
+    struct is_expected : std::false_type {};
+
+    template<typename T, typename E>
+    struct is_expected<expected<T, E>> : std::true_type {};
+
+    // true_type if E can be contained in an unexpected{} or !has_value
+    // expected.
+    template<typename E>
+    using can_be_unexpected_val = and_<
+      std::is_object<E>,
+      not_<std::is_array<E>>,
+      not_<is_unexpected<E>>,
+      not_<is_cv_qualified<E>>
+      >;
+
+    // true_type if T can be contained in a has_value expected.
+    template<typename T>
+    using can_be_expected_val_2 = or_<
+      std::is_same<T, void>,
+      and_<
+	std::is_object<T>,
+	not_<std::is_array<T>>,
+	not_<is_in_place<T>>,
+	not_<is_unexpected<T>>,
+	not_<std::is_same<T, unexpect_t>>
+	>
+      >;
+    template<typename T>
+    using can_be_expected_val = can_be_expected_val_2<std::remove_cv_t<T>>;
+
+    // true_type if T is void or Trait<T> holds.
+    template<template<typename> class Trait, typename T, typename = std::remove_cv_t<T>>
+    struct trait_or_void : Trait<T> {};
+
+    template<template<typename> class Trait, typename T>
+    struct trait_or_void<Trait, T, void> : std::true_type {};
+
+    // true_type if T is not void and Trait<T> holds.
+    template<template<typename> class Trait, typename T, typename = std::remove_cv_t<T>>
+    struct trait_and_nonvoid : Trait<T> {};
+
+    template<template<typename> class Trait, typename T>
+    struct trait_and_nonvoid<Trait, T, void> : std::false_type {};
+
+    // 'bool' if T1 is equality-comparable with T2, and E1 with E2, SFINAE-fail
+    // otherwise.  Used for comparisons of expected types.
+    template<typename T1, typename T2,
+	     typename E1, typename E2>
+    using eql_2_return_t = detail::relop_return_t<
+      decltype (std::declval<const T1&> () == std::declval<const T2&> ()),
+      decltype (std::declval<const E1&> () == std::declval<const E2&> ())
+      >;
+
+    // Implements the "U is a specialization of expected and is_same_v<typename
+    // U::error_type, E> is true." mandate where U=Candidate and E=WantedError.
+    template<typename Candidate, typename WantedError>
+    struct is_expected_with_same_error : std::false_type {};
+
+    template<typename T, typename E, typename WantedError>
+    struct is_expected_with_same_error<expected<T, E>, WantedError>
+      : std::is_same<E, WantedError> {};
+
+    // Implements the "G is a specialization of expected and
+    // is_same_v<typename G::value_type, T> is true." mandate, where
+    // G=Candidate and T=WantedValue.
+    template<typename Candidate, typename WantedValue>
+    struct is_expected_with_same_value : std::false_type {};
+
+    template<typename T, typename E, typename WantedValue>
+    struct is_expected_with_same_value<expected<T, E>, WantedValue>
+      : std::is_same<T, WantedValue> {};
+
+    // true_type if T is void or Trait<T> holds, and Trait<E> holds.
+    template<template<typename> class Trait, typename T, typename E>
+    using trait_2 = and_<trait_or_void<Trait, T>, Trait<E>>;
+
+    // Tag type, use supplied invocable to populate 'val'.
+    struct in_place_inv {};
+    // Likewise, but for 'unex'.
+    struct unexpect_inv {};
+  }} // namespace detail::exp
+
+  template<typename E>
+  struct unexpected
+  {
+    // [expected.un.general]p2
+    static_assert (detail::exp::can_be_unexpected_val<E>::value,
+		   "E not a valid type for unexpected<>");
+
+    // [expected.un.cons]
+    unexpected (const unexpected &) = default;
+    unexpected (unexpected &&) = default;
+
+    template<typename Err = E,
+	     typename = std::enable_if_t<and_<
+	       std::is_constructible<E, Err>,
+	       not_<is_in_place<Err>>,
+	       not_<std::is_same<g_remove_cvref_t<Err>, unexpected>>
+	       >::value>>
+    constexpr explicit
+    unexpected (Err &&err)
+      : unex (std::forward<Err>(err))
+    {}
+
+    template<typename... Args,
+	     typename = std::enable_if_t<
+	       std::is_constructible<E, Args...>::value
+	       >>
+    constexpr explicit
+    unexpected (in_place_t, Args&&... args)
+      : unex (std::forward<Args>(args)...)
+    {}
+
+    template<typename U, typename... Args,
+	     typename = std::enable_if_t<
+	       std::is_constructible<E, std::initializer_list<U>&, Args...>::value
+	       >>
+    constexpr explicit unexpected(in_place_t,
+				  std::initializer_list<U> il, Args&&... args)
+      : unex (il, std::forward<Args>(args)...)
+    {}
+
+    unexpected& operator= (const unexpected&) = default;
+    unexpected& operator= (unexpected&&) = default;
+
+    // [expected.un.obs]
+    [[nodiscard]] constexpr const E &
+    error () const & noexcept
+    { return unex; }
+
+    [[nodiscard]] constexpr E &
+    error () & noexcept
+    { return unex; }
+
+    [[nodiscard]] constexpr E &&
+    error() && noexcept
+    { return std::move (unex); }
+
+    [[nodiscard]] constexpr const E &&
+    error() const && noexcept
+    { return std::move (unex); }
+
+    // [expected.un.swap]
+    template<typename E_ = E>
+    constexpr std::enable_if_t<g_is_swappable<E_>::value>
+    swap (unexpected& other) noexcept (g_is_nothrow_swappable<E>::value)
+    {
+      using std::swap;
+      swap (unex, other.unex);
+    }
+
+    template<typename E_ = E>
+    friend constexpr std::enable_if_t<g_is_swappable<E_>::value>
+    swap (unexpected &x, unexpected &y) noexcept (noexcept (x.swap(y)))
+    { x.swap (y); }
+
+    // [expected.un.eq]
+    template<typename E2>
+    [[nodiscard]] friend constexpr eql_return_t<E, E2>
+    operator== (const unexpected &x, const unexpected<E2> &y)
+    { return x.error () == y.error (); }
+
+  private:
+    template<typename T2, typename E2>
+    friend struct expected;
+
+    E unex;
+  };
+
+  // EXTENSION: Permit deduction of 'unexpected' from value type.  Eventually
+  // to be replaced with a deduction guide.
+  template<typename E>
+  constexpr unexpected<std::decay_t<E>>
+  make_unexpected (E &&e)
+  { return unexpected<std::decay_t<E>> (std::forward<E> (e)); }
+
+#if __cpp_deduction_guides >= 201703L
+  template<class E> unexpected(E) -> unexpected<E>;
+#endif
+
+#ifdef GCC_BACKPORT_WANT_EXCEPTIONS
+  // Only implemented to permit running testsuites for <expected> against this
+  // implementation.  Never actually enabled.
+
+  // [expected.void.bad]
+  template<typename G_Er>
+    class bad_expected_access;
+
+#if __cpp_lib_constexpr_exceptions >= 202502L
+#define GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS constexpr
+#else
+#define GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS
+#endif
+
+  template<>
+    class bad_expected_access<void> : public std::exception
+    {
+    protected:
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS bad_expected_access() noexcept { }
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS
+      bad_expected_access (const bad_expected_access&) noexcept = default;
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS
+      bad_expected_access (bad_expected_access&&) noexcept = default;
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS
+      bad_expected_access& operator= (const bad_expected_access&) noexcept = default;
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS
+      bad_expected_access& operator= (bad_expected_access&&) noexcept = default;
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS
+      ~bad_expected_access () = default;
+
+    public:
+
+      [[nodiscard]]
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS const char*
+      what () const noexcept override
+      { return "bad access to std::expected without expected value"; }
+    };
+
+  // [expected.bad]
+  template<typename G_Er>
+    class bad_expected_access : public bad_expected_access<void> {
+    public:
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS explicit
+      bad_expected_access (G_Er g_e) : G_M_unex(std::move(g_e)) { }
+
+      // XXX const char* what() const noexcept override;
+
+      [[nodiscard]]
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS G_Er&
+      error () & noexcept
+      { return G_M_unex; }
+
+      [[nodiscard]]
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS const G_Er&
+      error () const & noexcept
+      { return G_M_unex; }
+
+      [[nodiscard]]
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS G_Er&&
+      error () && noexcept
+      { return std::move(G_M_unex); }
+
+      [[nodiscard]]
+      GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS const G_Er&&
+      error () const && noexcept
+      { return std::move(G_M_unex); }
+
+    private:
+      G_Er G_M_unex;
+    };
+#undef GCC_BACKPORT_CONSTEXPR_BAD_EXPECTED_ACCESS
+#endif // GCC_BACKPORT_WANT_EXCEPTIONS
+
+  namespace detail { namespace exp
+  {
+    struct in_value_t {};
+    // Tag, construct value field.
+    static constexpr in_value_t in_value;
+    struct in_unex_t {};
+    // Tag, construct unex field.
+    static constexpr in_unex_t in_unex;
+    struct in_unused_t {};
+    // Tag, construct unused field.
+    static constexpr in_unused_t in_unused;
+
+    // Replaces T=void for storage, and acts as a placeholder when storage is
+    // empty.
+    struct void_storage {};
+
+    // Storage type for the expected value.  T unless T is void, then
+    // void_storage.
+    template<typename T>
+    using good_storage = std::conditional_t<std::is_void<T>::value,
+					    void_storage, T>;
+
+#define GCC_EXP_STORAGE_2_COMMON			\
+    constexpr storage_2 () = default;			\
+							\
+    template<typename... Args>				\
+    constexpr storage_2 (in_value_t, Args&&... args)	\
+      : m_value (std::forward<Args> (args)...)		\
+      , m_has_value (true)				\
+    {}							\
+							\
+    template<typename... Args>				\
+    constexpr storage_2 (in_unex_t, Args&&... args)	\
+      : m_unex (std::forward<Args> (args)...)		\
+      , m_has_value (false)				\
+    {}							\
+							\
+    template<typename... Args>				\
+    constexpr storage_2 (in_unused_t, Args&&... args)	\
+      : m_unused (std::forward<Args> (args)...)		\
+	/* To appease constexpr; always overwritten. */	\
+      , m_has_value (false)				\
+    {}							\
+							\
+    template<typename Fn>				\
+    constexpr storage_2 (in_place_inv, Fn &&fn)		\
+      : m_value (std::forward<Fn> (fn) ())		\
+      , m_has_value (true)				\
+    {}							\
+							\
+    template<typename Fn>				\
+    constexpr storage_2 (unexpect_inv, Fn &&fn)		\
+      : m_unex (std::forward<Fn> (fn) ())		\
+      , m_has_value (false)				\
+    {}							\
+							\
+    GCC_BACKPORT20_CONSTEXPR void			\
+    clear_storage ()					\
+    {							\
+      if (this->m_has_value)				\
+	G_Destroy (std::addressof (this->m_value));	\
+      else						\
+	G_Destroy (std::addressof (this->m_unex));	\
+    }
+
+    // Container holding the contents of the expected.  Provides the
+    // destructor.
+    template<typename T, typename E,
+	     bool is_trivial = trait_2<std::is_trivially_destructible,
+				       T, E>::value>
+    struct storage_2
+    {
+      /* Non-trivially destructible T or E.  Need a hand-written
+	 destructor.  */
+      GCC_BACKPORT20_CONSTEXPR
+      ~storage_2 ()
+      { clear_storage (); }
+
+      GCC_EXP_STORAGE_2_COMMON
+
+      union {
+	void_storage m_unused;
+	good_storage<T> m_value;
+	E m_unex;
+      };
+      bool m_has_value;
+    };
+
+    template<typename T, typename E>
+    struct storage_2<T, E, true>
+    {
+      GCC_EXP_STORAGE_2_COMMON
+
+      union {
+	void_storage m_unused;
+	good_storage<T> m_value;
+	E m_unex;
+      };
+      bool m_has_value;
+    };
+#undef GCC_EXP_STORAGE_2_COMMON
+
+    // This layer provides some utilities.
+    template<typename T, typename E>
+    struct storage_1 : storage_2<T, E>
+    {
+      using storage_2<T, E>::storage_2;
+
+      // Getters preserving const-ness and ref-ness of *this.
+#define GCC_EXP_STORAGE_1_DO_GETTER(type, member, name)	\
+      constexpr type &name () & noexcept		\
+      { return this->member; }				\
+      constexpr const type &name () const & noexcept	\
+      { return this->member; }				\
+      constexpr type &&name () && noexcept		\
+      { return std::move (this->member); }		\
+      constexpr const type &&name () const && noexcept	\
+      { return std::move (this->member); }
+
+      GCC_EXP_STORAGE_1_DO_GETTER (T, m_value, value)
+      GCC_EXP_STORAGE_1_DO_GETTER (E, m_unex, unex)
+
+      // Helpers, for initial construction.
+      template<typename... Args>
+      constexpr void
+      construct_value (Args&&... args)
+      {
+	gcc::construct_at (std::addressof (this->m_value),
+			   std::forward<Args> (args)...);
+	this->m_has_value = true;
+      }
+
+      template<typename... Args>
+      constexpr void
+      construct_unex (Args&&... args)
+      {
+	gcc::construct_at (std::addressof (this->m_unex),
+			   std::forward<Args> (args)...);
+	this->m_has_value = false;
+      }
+
+      // Copy/move construct our value/unex field based on other storage.
+      // Presumes 'm_unused' is active right now.
+      template<typename Other>
+      constexpr
+      std::enable_if_t<std::is_convertible<std::remove_reference_t<Other> *,
+					   const volatile storage_1 *>::value>
+      construct (Other &&other)
+      {
+	if (other.m_has_value)
+	  this->construct_value (std::forward<Other> (other).value ());
+	else
+	  this->construct_unex (std::forward<Other> (other).unex ());
+      }
+
+      // reinit-expected exposition-only helper.
+      template<typename T2, typename U, typename... Args>
+      GCC_BACKPORT20_CONSTEXPR
+      std::enable_if_t<std::is_nothrow_constructible<T2, Args...>::value>
+      reinit_expected (T2& newval, U& oldval, Args&&... args)
+      {
+	gcc::G_Destroy (std::addressof (oldval));
+	gcc::construct_at (std::addressof (newval),
+			   std::forward<Args> (args)...);
+      }
+
+      template<typename T2, typename U, typename... Args>
+      GCC_BACKPORT20_CONSTEXPR
+      std::enable_if_t<
+	and_<not_<std::is_nothrow_constructible<T2, Args...>>,
+	     std::is_nothrow_move_constructible<T2>
+	     >::value
+	>
+      reinit_expected (T2& newval, U& oldval, Args&&... args)
+      {
+	T2 tmp (std::forward<Args> (args)...);
+	gcc::G_Destroy (std::addressof (oldval));
+	gcc::construct_at (std::addressof (newval), std::move (tmp));
+      }
+
+      template<typename T2, typename U, typename... Args>
+      GCC_BACKPORT20_CONSTEXPR
+      std::enable_if_t<
+	and_<not_<std::is_nothrow_constructible<T2, Args...>>,
+	     not_<std::is_nothrow_move_constructible<T2>>
+	     >::value
+	>
+      reinit_expected (T2& newval, U& oldval, Args&&... args)
+      {
+	U tmp (std::move (oldval));
+	gcc::G_Destroy (std::addressof (oldval));
+	g_try
+	  {
+	    gcc::construct_at (std::addressof (newval),
+			       std::forward<Args> (args)...);
+	  }
+	g_catch (...)
+	  {
+	    gcc::construct_at (std::addressof (oldval),
+			       std::move (tmp));
+	    g_throw_exception_again;
+	  }
+      }
+
+      // Assign m_value.
+      template<typename U>
+      GCC_BACKPORT20_CONSTEXPR void
+      assign_value (U &&v)
+      {
+	if (this->m_has_value)
+	  // "If has_value() is true, equivalent to: val = std::forward<U>(v);"
+	  this->m_value = std::forward<U> (v);
+	else
+	  // "Otherwise, equivalent to: reinit-expected(val, unex,
+	  // std::forward<U>(v)); has_val = true;"
+	  {
+	    reinit_expected (this->m_value, this->m_unex, std::forward<U> (v));
+	    this->m_has_value = true;
+	  }
+      }
+
+      // Assign m_unex.
+      template<typename Other>
+      GCC_BACKPORT20_CONSTEXPR void
+      assign_unex (Other &&other)
+      {
+
+	if (this->m_has_value)
+	  // "If has_value() is true, equivalent to: reinit-expected(unex, val,
+	  // std::forward<GF>(e.error())); has_val = false;"
+	  {
+	    // Must clear value first.
+	    reinit_expected (this->m_unex, this->m_value,
+			     std::forward<Other> (other));
+	    this->m_has_value = false;
+	  }
+	else
+	  // "Otherwise, equivalent to: unex = std::forward<GF>(e.error());"
+	  this->m_unex = std::forward<Other> (other);
+
+	// Note that the std::forward<GF> (e.error ()) bit is hoisted to the
+	// caller.
+      }
+
+      // Non-trivial move/copy assignment implementation.  OTHER must be a
+      // storage_1.  Called by the respective special member
+      template<typename Other>
+      GCC_BACKPORT20_CONSTEXPR
+      std::enable_if_t<std::is_convertible<std::remove_reference_t<Other> *,
+					   const volatile storage_1 *>::value>
+      assign (Other &&other)
+      {
+	if (this->m_has_value && other.m_has_value)
+	  // "If this->has_value() && rhs.has_value() is true, equivalent to
+	  // val = *rhs." / "If this->has_value() && rhs.has_value() is true,
+	  // equivalent to val = std::move(*rhs)."
+	  this->m_value = std::forward<Other> (other).value ();
+	else if (this->m_has_value)
+	  // "Otherwise, if this->has_value() is true, equivalent to:
+	  // reinit-expected(unex, val, rhs.error())" / "Otherwise, if
+	  // this->has_value() is true, equivalent to: reinit-expected(unex,
+	  // val, std::move(rhs.error()))"
+	  reinit_expected (this->m_unex, this->m_value,
+			   std::forward<Other> (other).unex ());
+	else if (other.m_has_value)
+	  // "Otherwise, if rhs.has_value() is true, equivalent to:
+	  // reinit-expected(val, unex, *rhs)" / "Otherwise, if rhs.has_value()
+	  // is true, equivalent to: reinit-expected(val, unex,
+	  // std::move(*rhs))"
+	  reinit_expected (this->m_value, this->m_unex,
+			   std::forward<Other> (other).value ());
+	else
+	  // Otherwise, equivalent to unex = std::move(rhs.error()).
+	  this->m_unex = std::forward<Other> (other).unex ();
+	// Then, if no exception was thrown, equivalent to: has_val =
+	// rhs.has_value(); return *this;
+	this->m_has_value = other.m_has_value;
+      }
+
+      // [expected.object.swap]p2 "For the case where rhs.has_value() is false
+      // and this->has_value() is true", without the final 'has_val'
+      // reassignments.
+      template<typename T2, typename E2>
+      GCC_BACKPORT20_CONSTEXPR
+      std::enable_if_t<std::is_nothrow_move_constructible<E2>::value>
+      swap_1 (T2 &val, E2 &unex,
+	      T2 &rhs_val, E2 &rhs_unex)
+      {
+	E tmp (std::move(rhs_unex));
+	gcc::G_Destroy (std::addressof (rhs_unex));
+	g_try
+	  {
+	    gcc::construct_at (std::addressof (rhs_val), std::move (val));
+	    gcc::G_Destroy (std::addressof (val));
+	    gcc::construct_at (std::addressof (unex), std::move(tmp));
+	  }
+	g_catch (...)
+	  {
+	    gcc::construct_at (std::addressof (rhs_unex), std::move(tmp));
+	    g_throw_exception_again;
+	  }
+      }
+
+      template<typename T2, typename E2>
+      GCC_BACKPORT20_CONSTEXPR
+      std::enable_if_t<!std::is_nothrow_move_constructible<E2>::value>
+      swap_1 (T2 &val, E2 &unex,
+	      T2 &rhs_val, E2 &rhs_unex)
+      {
+	static_assert (std::is_nothrow_move_constructible<T2>::value,
+		       "Can't swap without a nothrow-move-constructible T or E"
+		       ", is a constraint missing on swap?");
+	T tmp (std::move (val));
+	gcc::G_Destroy (std::addressof (val));
+	g_try
+	  {
+	    gcc::construct_at (std::addressof (unex), std::move (rhs_unex));
+	    gcc::G_Destroy(std::addressof (rhs_unex));
+	    gcc::construct_at (std::addressof (rhs_val), std::move (tmp));
+	  }
+	g_catch (...)
+	  {
+	    gcc::construct_at (std::addressof (val), std::move (tmp));
+	    g_throw_exception_again;
+	  }
+      }
+
+      GCC_BACKPORT20_CONSTEXPR void
+      _swap (storage_1 &other)
+      {
+	using std::swap;
+
+	if (this->m_has_value && other.m_has_value)
+	  swap (this->m_value, other.m_value);
+	else if (!this->m_has_value && !other.m_has_value)
+	  swap (this->m_unex, other.m_unex);
+	else if (!this->m_has_value && other.m_has_value)
+	  other._swap (*this);
+	else
+	  {
+	    swap_1<T, E> (this->m_value, this->m_unex,
+			  other.m_value, other.m_unex);
+	    this->m_has_value = false;
+	    other.m_has_value = true;
+	  }
+      }
+    };
+
+    // Void specialization
+    template<typename E>
+    struct storage_1<void, E> : storage_2<void, E>
+    {
+      using storage_2<void, E>::storage_2;
+
+      // "Hijack" the in_place_inv constructor, because we can't initialize a
+      // void_storage with a void
+      template<typename Fn>
+      constexpr storage_1 (in_place_inv, Fn &&fn)
+	: storage_2<void, E> (in_value)
+      { std::forward<Fn> (fn) (); }
+
+      GCC_EXP_STORAGE_1_DO_GETTER (E, m_unex, unex)
+
+#undef GCC_EXP_STORAGE_1_DO_GETTER
+
+      constexpr void
+      construct_value ()
+      {
+	gcc::construct_at (std::addressof (this->m_value));
+	this->m_has_value = true;
+      }
+
+      template<typename... Args>
+      constexpr void
+      construct_unex (Args&&... args)
+      {
+	gcc::construct_at (std::addressof (this->m_unex),
+			   std::forward<Args> (args)...);
+	this->m_has_value = false;
+      }
+
+      // Copy/move construct our value/unex field based on other storage.
+      // Presumes 'm_unused' is active right now.
+      template<typename Other>
+      constexpr
+      std::enable_if_t<std::is_convertible<std::remove_reference_t<Other> *,
+					   const volatile storage_1 *>::value>
+      construct (Other &&other)
+      {
+	if (other.m_has_value)
+	  this->m_has_value = true;
+	else
+	  this->construct_unex (std::forward<Other> (other).unex ());
+      }
+
+      template<typename Other>
+      constexpr void
+      assign_unex (Other &&other)
+      {
+	if (this->m_has_value)
+	  this->construct_unex (std::forward<Other> (other));
+	else
+	  this->m_unex = std::forward<Other> (other);
+      }
+
+      template<typename Other>
+      constexpr
+      std::enable_if_t<std::is_convertible<std::remove_reference_t<Other> *,
+					   const volatile storage_1 *>::value>
+      assign (Other &&other)
+      {
+	if (this->m_has_value)
+	  {
+	    if (other.m_has_value)
+	      ; // "If this->has_value() && rhs.has_value() is true, no effects."
+	    else
+	      // "Otherwise, if this->has_value() is true, equivalent to:
+	      // construct_at(addressof(unex), rhs.unex); has_val = false;"
+	      this->construct_unex (std::forward<Other> (other).unex ());
+	  }
+	else
+	  {
+	    if (other.m_has_value)
+	      {
+		// "Otherwise, if rhs.has_value() is true, destroys unex and
+		// sets has_val to true."
+		gcc::G_Destroy (std::addressof (this->m_unex));
+		construct_value ();
+	      }
+	    else
+	      // "Otherwise, equivalent to unex = rhs.error()."
+	      this->m_unex = std::forward<Other> (other).unex ();
+	  }
+      }
+
+      GCC_BACKPORT20_CONSTEXPR void
+      _swap (storage_1 &other)
+      {
+	using std::swap;
+
+	if (this->m_has_value && other.m_has_value)
+	  ;
+	else if (!this->m_has_value && !other.m_has_value)
+	  swap (this->m_unex, other.m_unex);
+	else if (!this->m_has_value && other.m_has_value)
+	  other._swap (*this);
+	else
+	  {
+	    gcc::construct_at (std::addressof (this->m_unex),
+			       std::move (other.m_unex));
+	    gcc::G_Destroy (std::addressof (other.m_unex));
+	    this->m_has_value = false;
+	    other.construct_value ();
+	  }
+      }
+    };
+
+    // Copy operations.
+    template<typename T, typename E,
+	     bool is_trivial = trait_2<std::is_trivially_copy_constructible,
+				       T, E>::value>
+    struct storage_copy_cons;
+
+    template<typename T, typename E>
+    struct storage_copy_cons<T, E, true> : storage_1<T, E>
+    {
+      using storage_1<T, E>::storage_1;
+      storage_copy_cons (storage_copy_cons &&) = default;
+      storage_copy_cons &
+      operator= (const storage_copy_cons& other) = default;
+      storage_copy_cons &
+      operator= (storage_copy_cons&& other) = default;
+
+      // Does not require explicit copy constructor.
+      storage_copy_cons(const storage_copy_cons &) = default;
+    };
+
+    template<typename T, typename E>
+    struct storage_copy_cons<T, E, false> : storage_1<T, E>
+    {
+      using storage_1<T, E>::storage_1;
+      storage_copy_cons (storage_copy_cons &&) = default;
+      storage_copy_cons &
+      operator= (const storage_copy_cons& other) = default;
+      storage_copy_cons &
+      operator= (storage_copy_cons&& other) = default;
+
+      // Requires explicit copy constructor.
+      constexpr
+      storage_copy_cons(const storage_copy_cons &o)
+	: storage_1<T, E>(in_unused)
+      { this->construct (o); }
+    };
+
+    template<typename T, typename E,
+	     bool is_trivial = and_<
+	       trait_or_void<std::is_trivially_copy_constructible, T>,
+	       trait_or_void<std::is_trivially_copy_assignable, T>,
+	       trait_or_void<std::is_trivially_destructible, T>,
+	       std::is_trivially_copy_constructible<E>,
+	       std::is_trivially_copy_assignable<E>,
+	       std::is_trivially_destructible<E>
+	       >::value>
+    struct storage_copy_assign;
+
+    template<typename T, typename E>
+    struct storage_copy_assign<T, E, true> : storage_copy_cons<T, E>
+    {
+      using storage_copy_cons<T, E>::storage_copy_cons;
+      storage_copy_assign (const storage_copy_assign &) = default;
+      storage_copy_assign (storage_copy_assign &&) = default;
+      storage_copy_assign &
+      operator= (storage_copy_assign&& other) = default;
+
+      // Trivially copy-assignable.
+      storage_copy_assign &
+      operator= (const storage_copy_assign& other)
+	noexcept (and_<trait_2<std::is_nothrow_copy_assignable, T, E>,
+		       trait_2<std::is_nothrow_copy_constructible, T, E>>::value)
+      = default;
+    };
+
+    template<typename T, typename E>
+    struct storage_copy_assign<T, E, false> : storage_copy_cons<T, E>
+    {
+      using storage_copy_cons<T, E>::storage_copy_cons;
+      storage_copy_assign (const storage_copy_assign &) = default;
+      storage_copy_assign (storage_copy_assign &&) = default;
+      storage_copy_assign &
+      operator= (storage_copy_assign&& other) = default;
+
+      // Requires explicit copy assignment.
+      GCC_BACKPORT20_CONSTEXPR storage_copy_assign &
+      operator= (const storage_copy_assign& other)
+	noexcept (and_<trait_2<std::is_nothrow_copy_assignable, T, E>,
+		       trait_2<std::is_nothrow_copy_constructible, T, E>>::value)
+      {
+	this->assign (other);
+	return *this;
+      }
+    };
+
+    // Move operations.
+    template<typename T, typename E,
+	     bool is_trivial = trait_2<std::is_trivially_move_constructible,
+				       T, E>::value>
+    struct storage_move_cons;
+
+    template<typename T, typename E>
+    struct storage_move_cons<T, E, true> : storage_copy_assign<T, E>
+    {
+      using storage_copy_assign<T, E>::storage_copy_assign;
+      storage_move_cons(const storage_move_cons &) = default;
+      storage_move_cons &
+      operator= (const storage_move_cons &) = default;
+      storage_move_cons &
+      operator= (storage_move_cons &&) = default;
+
+      // Does not require explicit move constructor.
+      storage_move_cons(storage_move_cons &&) = default;
+    };
+
+    template<typename T, typename E>
+    struct storage_move_cons<T, E, false> : storage_copy_assign<T, E>
+    {
+      using storage_copy_assign<T, E>::storage_copy_assign;
+      storage_move_cons (const storage_move_cons &) = default;
+      storage_move_cons &operator= (const storage_move_cons &) = default;
+      storage_move_cons &operator= (storage_move_cons &&) = default;
+
+      // Requires explicit move constructor.
+      constexpr
+      storage_move_cons (storage_move_cons &&o)
+	noexcept (trait_2<std::is_nothrow_move_constructible, T, E>::value)
+	: storage_copy_assign<T, E>(in_unused)
+      { this->construct (std::move (o)); }
+    };
+
+    template<typename T, typename E,
+	     bool is_trivial = and_<
+	       trait_2<std::is_trivially_move_constructible, T, E>,
+	       trait_2<std::is_trivially_move_assignable, T, E>,
+	       trait_2<std::is_trivially_destructible, T, E>
+	       >::value>
+    struct storage_move_assign;
+
+    template<typename T, typename E>
+    struct storage_move_assign<T, E, true> : storage_move_cons<T, E>
+    {
+      using storage_move_cons<T, E>::storage_move_cons;
+      storage_move_assign (storage_move_assign&&) = default;
+      storage_move_assign (const storage_move_assign&) = default;
+      storage_move_assign&
+      operator= (const storage_move_assign&) = default;
+
+      // Trivially move-assignable.
+      storage_move_assign &
+      operator= (storage_move_assign&& other)
+	noexcept (and_<trait_2<std::is_nothrow_move_assignable, T, E>,
+		       trait_2<std::is_nothrow_move_constructible, T, E>>::value)
+      = default;
+    };
+
+    template<typename T, typename E>
+    struct storage_move_assign<T, E, false> : storage_move_cons<T, E>
+    {
+      using storage_move_cons<T, E>::storage_move_cons;
+      storage_move_assign (storage_move_assign&&) = default;
+      storage_move_assign (const storage_move_assign&) = default;
+      storage_move_assign&
+      operator= (const storage_move_assign&) = default;
+
+      // Requires explicit move assignment.
+      GCC_BACKPORT20_CONSTEXPR storage_move_assign &
+      operator= (storage_move_assign&& other)
+	noexcept (and_<trait_2<std::is_nothrow_move_assignable, T, E>,
+		       trait_2<std::is_nothrow_move_constructible, T, E>>::value)
+      {
+	this->assign (std::move (other));
+	return *this;
+      }
+    };
+
+    // Default construction.
+    template<typename T, typename E,
+	     bool is_deault_cons = trait_or_void<
+	       std::is_default_constructible, T
+	       >::value>
+    struct storage_default_cons;
+
+    template<typename T, typename E>
+    struct storage_default_cons<T, E, false> : storage_move_assign<T, E>
+    {
+      using storage_move_assign<T, E>::storage_move_assign;
+      // No default constructor.
+      constexpr storage_default_cons () = delete;
+    };
+
+    template<typename T, typename E>
+    struct storage_default_cons<T, E, true> : storage_move_assign<T, E>
+    {
+      using storage_move_assign<T, E>::storage_move_assign;
+      constexpr storage_default_cons ()
+	: storage_move_assign<T, E> (in_value)
+      {}
+    };
+
+    // Final link in the chain.
+    template<typename T, typename E>
+    using storage = storage_default_cons<T, E>;
+  }} // namespace detail::exp
+
+  // [expected.expected]
+  template<typename T, typename E>
+  struct [[nodiscard]] expected
+    : private detail::exp::storage<std::remove_cv_t<T>, E>
+    , private G_Enable_copy_move<
+	// Copy constructor.
+	detail::exp::trait_2<std::is_copy_constructible, T, E>::value,
+	// Copy assignment.
+	and_<detail::exp::trait_2<std::is_copy_assignable, T, E>,
+	     detail::exp::trait_2<std::is_copy_constructible, T, E>,
+	     or_<detail::exp::trait_or_void<std::is_nothrow_move_constructible, T>,
+		 std::is_nothrow_move_constructible<E>>
+	     >::value,
+	// Move constructor.
+	detail::exp::trait_2<std::is_move_constructible, T, E>::value,
+	// Move assignment.
+	and_<detail::exp::trait_2<std::is_move_assignable, T, E>,
+	     detail::exp::trait_2<std::is_move_constructible, T, E>,
+	     or_<detail::exp::trait_or_void<std::is_nothrow_move_constructible, T>,
+		 std::is_nothrow_move_constructible<E>>>::value
+      >
+  {
+  private:
+    using storage = detail::exp::storage<std::remove_cv_t<T>, E>;
+
+    // Usage: <typename T_ = T, Require_non_void<T_> = false>.
+    template<typename T_>
+    using Require_non_void = G_Requires<not_<std::is_void<T_>>>;
+
+    // Usage: <typename T_ = T> Non_void<T>.
+    template<typename T_>
+    using Non_void = std::enable_if_t<!std::is_void<T_>::value, T_>;
+
+    // Usage: <typename T_ = T> Only_void<T>.
+    template<typename T_>
+    using Only_void = std::enable_if_t<std::is_void<T_>::value>;
+
+    // If T is not cv bool, converts-from-any-cvref<T, expected<U, G>> and
+    // is_constructible<unexpected<E>, cv expected<U, G> ref-qual> are false.
+    template<typename G_Up, typename G_Gr, typename G_Unex = unexpected<E>,
+	     typename = std::remove_cv_t<T>>
+    struct g_cons_from_expected
+      : or_<std::is_constructible<T, expected<G_Up, G_Gr>&>,
+	    std::is_constructible<T, expected<G_Up, G_Gr>>,
+	    std::is_constructible<T, const expected<G_Up, G_Gr>&>,
+	    std::is_constructible<T, const expected<G_Up, G_Gr>>,
+	    std::is_convertible<expected<G_Up, G_Gr>&, T>,
+	    std::is_convertible<expected<G_Up, G_Gr>, T>,
+	    std::is_convertible<const expected<G_Up, G_Gr>&, T>,
+	    std::is_convertible<const expected<G_Up, G_Gr>, T>,
+	    std::is_constructible<G_Unex, expected<G_Up, G_Gr>&>,
+	    std::is_constructible<G_Unex, expected<G_Up, G_Gr>>,
+	    std::is_constructible<G_Unex, const expected<G_Up, G_Gr>&>,
+	    std::is_constructible<G_Unex, const expected<G_Up, G_Gr>>
+	    >
+    {};
+
+    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+    // If t is cv bool, we know it can be constructed from expected<U, G>,
+    // but we don't want to cause the expected(U&&) constructor to be used,
+    // so we only check the is_constructible<unexpected<E>, ...> cases.
+    template<typename G_Up, typename G_Gr, typename G_Unex>
+    struct g_cons_from_expected<G_Up, G_Gr, G_Unex, bool>
+      : or_<std::is_constructible<G_Unex, expected<G_Up, G_Gr>&>,
+	      std::is_constructible<G_Unex, expected<G_Up, G_Gr>>,
+	      std::is_constructible<G_Unex, const expected<G_Up, G_Gr>&>,
+	      std::is_constructible<G_Unex, const expected<G_Up, G_Gr>>
+	      >
+    {};
+
+    // For the void specialization
+    template<typename G_Up, typename G_Gr, typename G_Unex>
+    struct g_cons_from_expected<G_Up, G_Gr, G_Unex, void>
+      : or_<std::is_constructible<G_Unex, expected<G_Up, G_Gr>&>,
+	    std::is_constructible<G_Unex, expected<G_Up, G_Gr>>,
+	    std::is_constructible<G_Unex, const expected<G_Up, G_Gr>&>,
+	    std::is_constructible<G_Unex, const expected<G_Up, G_Gr>>
+	    >
+    {};
+
+    template<typename G_Up, typename G_Gr>
+    using g_explicit_conv
+    = or_<not_<std::is_convertible<G_Up, T>>,
+	  not_<std::is_convertible<G_Gr, E>>
+	  >;
+
+    // Constraints for <swap>
+    template<typename T_, typename E_, bool = std::is_void<T_>::value>
+    struct Constrain_swap_ : and_<
+      g_is_swappable<T_>,
+      g_is_swappable<E_>,
+      std::is_move_constructible<T_>,
+      std::is_move_constructible<E_>,
+      or_<
+	std::is_nothrow_move_constructible<T_>,
+	std::is_nothrow_move_constructible<E_>
+	>
+      >
+    {};
+
+    // When T=void
+    template<typename T_, typename E_>
+    struct Constrain_swap_<T_, E_, true> : and_<
+      g_is_swappable<E_>,
+      std::is_move_constructible<E_>
+      >
+    {};
+
+    template<typename T_, typename E_>
+    using Constrain_swap = std::enable_if_t<Constrain_swap_<T_, E_>::value>;
+
+  public:
+    static_assert (detail::exp::can_be_unexpected_val<E>::value,
+		   "E not a valid expected error type");
+    static_assert (detail::exp::can_be_expected_val<T>::value,
+		   "T cannot be unexpected<>");
+
+    using value_type = T;
+    using error_type = E;
+    using unexpected_type = unexpected<E>;
+
+    template<typename U>
+    using rebind = expected<U, error_type>;
+
+    // [expected.object.obs] & [expected.void.obs]
+
+    // [expected.object.obs]p1
+    template<typename T_ = T>
+    [[nodiscard]] constexpr const Non_void<T_>*
+    operator-> () const noexcept
+    {
+      gccbackport_assert (this->m_has_value && "Accessing value of expected with no value");
+      return std::addressof (this->m_value);
+    }
+
+    template<typename T_ = T>
+    [[nodiscard]] constexpr Non_void<T_>*
+    operator-> () noexcept
+    {
+      gccbackport_assert (this->m_has_value && "Accessing value of expected with no value");
+      return std::addressof (this->m_value);
+    }
+
+    // [expected.object.obs]p3
+    template<typename T_ = T>
+    [[nodiscard]] constexpr const Non_void<T_> &
+    operator* () const & noexcept
+    {
+      gccbackport_assert (this->m_has_value && "Accessing value of expected with no value");
+      return this->m_value;
+    }
+
+    template<typename T_ = T>
+    [[nodiscard]] constexpr Non_void<T_> &
+    operator* () & noexcept
+    {
+      gccbackport_assert (this->m_has_value && "Accessing value of expected with no value");
+      return this->m_value;
+    }
+
+    // [expected.object.obs]p5
+    template<typename T_ = T>
+    [[nodiscard]] constexpr Non_void<T_> &&
+    operator* () && noexcept
+    {
+      gccbackport_assert (this->m_has_value && "Accessing value of expected with no value");
+      return std::move (this->m_value);
+    }
+
+    template<typename T_ = T>
+    [[nodiscard]] constexpr const Non_void<T_> &&
+    operator* () const && noexcept
+    {
+      gccbackport_assert (this->m_has_value && "Accessing value of expected with no value");
+      return std::move (this->m_value);
+    }
+
+    // [expected.void.obs]p3
+    template<typename T_ = T>
+    [[nodiscard]] constexpr Only_void<T_>
+    operator* () const noexcept
+    {
+      gccbackport_assert (this->m_has_value && "Accessing value of expected with no value");
+    }
+
+    // [expected.object.obs]p7
+    [[nodiscard]] constexpr explicit
+    operator bool () const noexcept
+    { return this->m_has_value; }
+
+    [[nodiscard]] constexpr bool
+    has_value () const noexcept
+    { return this->m_has_value; }
+
+    // [expected.object.obs]p8
+    [[nodiscard]] constexpr bool
+    has_error () const noexcept
+    { return !this->m_has_value; }
+
+    // TODO(arsen): restore [[likely]]
+
+    // [expected.object.obs]p9
+    template<typename T_ = T>
+    constexpr const Non_void<T_> &
+    value () const &
+    {
+      static_assert (std::is_copy_constructible<E>::value, "");
+      if (this->m_has_value)
+	return this->m_value;
+      g_throw_or_abort (bad_expected_access<E> (gcc::as_const (error ())));
+    }
+
+    template<typename T_ = T>
+    constexpr Non_void<T_> &
+    value () &
+    {
+      static_assert (std::is_copy_constructible<E>::value, "");
+      if (this->m_has_value)
+	return this->m_value;
+      g_throw_or_abort (bad_expected_access<E> (gcc::as_const (error ())));
+    }
+
+    // [expected.object.obs]p12
+    template<typename T_ = T>
+    constexpr const Non_void<T_> &&
+    value () const &&
+    {
+      static_assert (std::is_copy_constructible<E>::value, "");
+      static_assert (std::is_constructible<E, const E&&>::value, "");
+      if (this->m_has_value)
+	return std::move (this->m_value);
+      g_throw_or_abort (bad_expected_access<E> (std::move (error ())));
+    }
+
+    template<typename T_ = T>
+    constexpr Non_void<T_> &&
+    value () &&
+    {
+      static_assert (std::is_copy_constructible<E>::value, "");
+      static_assert (std::is_constructible<E, E&&>::value, "");
+      if (this->m_has_value)
+	return std::move (this->m_value);
+      g_throw_or_abort (bad_expected_access<E> (std::move (error ())));
+    }
+
+    // [expected.void.obs]p4
+    template<typename T_ = T>
+    constexpr Only_void<T_>
+    value () const &
+    {
+      static_assert (std::is_copy_constructible<E>::value, "");
+      if (!this->m_has_value)
+	g_throw_or_abort (bad_expected_access<E> (error ()));
+    }
+
+    // [expected.void.obs]p6
+    template<typename T_ = T>
+    constexpr Only_void<T_>
+    value () &&
+    {
+      static_assert (std::is_copy_constructible<E>::value, "");
+      static_assert (std::is_constructible<E, E&&>::value, "");
+      if (!this->m_has_value)
+	g_throw_or_abort (bad_expected_access<E> (std::move (error ())));
+    }
+
+    // [expected.object.obs]p15
+    constexpr const E&
+    error () const & noexcept
+    {
+      gccbackport_assert (!this->m_has_value && "Accessing error of expected with no error");
+      return this->m_unex;
+    }
+
+    constexpr E&
+    error () & noexcept
+    {
+      gccbackport_assert (!this->m_has_value && "Accessing error of expected with no error");
+      return this->m_unex;
+    }
+
+    // [expected.object.obs]p17
+    constexpr const E&&
+    error () const && noexcept
+    {
+      gccbackport_assert (!this->m_has_value && "Accessing error of expected with no error");
+      return std::move (this->m_unex);
+    }
+
+    constexpr E&&
+    error () && noexcept
+    {
+      gccbackport_assert (!this->m_has_value && "Accessing error of expected with no error");
+      return std::move (this->m_unex);
+    }
+
+    // [expected.object.obs]p19
+    template<typename U = std::remove_cv_t<T>,
+	     typename T_ = T>
+    constexpr Non_void<T_>
+    value_or (U &&v) const &
+    {
+      static_assert (std::is_convertible<U, T>::value,
+		     "lvalue-reference value_or requires that type of "
+		     "argument is convertible to the value type");
+      static_assert (std::is_copy_constructible<T>::value,
+		     "lvalue-reference value_or requires that value type is "
+		     "copy-constructible");
+      return (this->m_has_value
+	      ? this->m_value
+	      : static_cast<T> (std::forward<U> (v)));
+    }
+
+    // [expected.object.obs]p21
+    template<typename U = std::remove_cv_t<T>,
+	     typename T_ = T>
+    constexpr Non_void<T_>
+    value_or (U &&v) &&
+    {
+      static_assert (std::is_convertible<U, T>::value,
+		     "rvalue-reference value_or requires that type of "
+		     "argument is convertible to the value type");
+      static_assert (std::is_move_constructible<T>::value,
+		     "rvalue-reference value_or requires that value type is "
+		     "move-constructible");
+      return (this->m_has_value
+	      ? std::move (this->m_value)
+	      : static_cast<T> (std::forward<U> (v)));
+    }
+
+    // [expected.object.obs]p23
+    template<typename G = E>
+    constexpr E
+    error_or (G &&e) const &
+    {
+      static_assert (std::is_convertible<G, E>::value,
+		     "lvalue-reference value_or requires that type of "
+		     "argument is convertible to the value type");
+      static_assert (std::is_copy_constructible<E>::value,
+		     "lvalue-reference error_or requires that error type is "
+		     "copy-constructible");
+      if (this->m_has_value)
+	return std::forward<G> (e);
+      return this->m_unex;
+    }
+
+    // [expected.object.obs]p26
+    template<typename G = E>
+    constexpr E
+    error_or (G &&e) &&
+    {
+      static_assert (std::is_convertible<G, E>::value,
+		     "rvalue-reference value_or requires that type of "
+		     "argument is convertible to the value type");
+      static_assert (std::is_move_constructible<E>::value,
+		     "rvalue-reference error_or requires that error type is "
+		     "move-constructible");
+      if (this->m_has_value)
+	return std::forward<G> (e);
+      return std::move (this->m_unex);
+    }
+
+    // Constructors [expected.object.cons]
+
+    // [expected.object.cons]p1; condition provided by subclass
+    expected() = default;
+
+    // [expected.object.cons]p6 and [expected.object.cons]p11 - the copy/move
+    // constructors - are implemented by storage and constrained by
+    // G_Enable_copy_move.
+    expected(const expected&) = default;
+    expected(expected&&) = default;
+
+    // [expected.object.cons]p17
+    template<typename U, typename G,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       // Constraints:
+	       not_<g_cons_from_expected<U, G>>,
+	       std::is_constructible<T_, const U&>,
+	       std::is_constructible<E, const G&>,
+
+	       // !Explicit:
+	       not_<g_explicit_conv<const U&, const G&>>
+	       > = false>
+    constexpr expected (const expected<U, G>& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->construct_value (rhs.value ());
+      else
+	this->construct_unex (rhs.error ());
+    }
+
+    template<typename U, typename G,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       // Constraints:
+	       not_<g_cons_from_expected<U, G>>,
+	       std::is_constructible<T_, const U&>,
+	       std::is_constructible<E, const G&>,
+
+	       // Explicit:
+	       g_explicit_conv<const U&, const G&>
+	       > = false>
+    constexpr explicit expected (const expected<U, G>& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->construct_value (rhs.value ());
+      else
+	this->construct_unex (rhs.error ());
+    }
+
+    template<typename U, typename G,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       // Constraints:
+	       not_<g_cons_from_expected<U, G>>,
+	       std::is_constructible<T_, U&&>,
+	       std::is_constructible<E, G&&>,
+
+	       // !Explicit:
+	       not_<g_explicit_conv<U, G>>
+	       > = false>
+    constexpr expected (expected<U, G>&& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->construct_value (std::move (rhs.m_value));
+      else
+	this->construct_unex (std::move (rhs.m_unex));
+    }
+
+    template<typename U, typename G,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       // Constraints:
+	       not_<g_cons_from_expected<U, G>>,
+	       std::is_constructible<T_, U&&>,
+	       std::is_constructible<E, G&&>,
+
+	       // Explicit:
+	       g_explicit_conv<U, G>
+	       > = false>
+    constexpr explicit expected (expected<U, G>&& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->construct_value (std::move (rhs.m_value));
+      else
+	this->construct_unex (std::move (rhs.m_unex));
+    }
+
+    // [expected.object.cons]p23
+    template<typename U = std::remove_cv_t<T>,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       // Constraints:
+	       not_<std::is_same<g_remove_cvref_t<U>, in_place_t>>,
+	       not_<std::is_same<g_remove_cvref_t<U>, expected>>,
+	       not_<std::is_same<g_remove_cvref_t<U>, unexpect_t>>,
+	       not_<detail::exp::is_unexpected<g_remove_cvref_t<U>>>,
+	       std::is_constructible<T_, U>,
+	       // "if T is cv bool, remove_cvref_t<U> is not a specialization
+	       // of expected"
+	       or_<not_<std::is_same<std::remove_cv_t<T_>, bool>>,
+		   not_<detail::exp::is_expected<g_remove_cvref_t<U>>>>,
+
+	       // !Explicit:
+	       std::is_convertible<U, T_>
+	       > = false>
+    constexpr expected (U&& v)
+      : storage (detail::exp::in_value, std::forward<U> (v))
+    {}
+
+    template<typename U = std::remove_cv_t<T>,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       // Constraints:
+	       not_<std::is_same<g_remove_cvref_t<U>, in_place_t>>,
+	       not_<std::is_same<g_remove_cvref_t<U>, expected>>,
+	       not_<std::is_same<g_remove_cvref_t<U>, unexpect_t>>,
+	       not_<detail::exp::is_unexpected<g_remove_cvref_t<U>>>,
+	       std::is_constructible<T_, U>,
+	       // "if T is cv bool, remove_cvref_t<U> is not a specialization
+	       // of expected"
+	       or_<not_<std::is_same<std::remove_cv_t<T_>, bool>>,
+		   not_<detail::exp::is_expected<g_remove_cvref_t<U>>>>,
+
+	       // Explicit:
+	       not_<std::is_convertible<U, T_>>
+	       > = false>
+    constexpr explicit expected (U&& v)
+      : storage (detail::exp::in_value, std::forward<U> (v))
+    {}
+
+    // [expected.object.cons]p27
+    template<typename G,
+	     G_Requires<
+	       // Constraints:
+	       std::is_constructible<E, const G&>,
+
+	       // !Explicit:
+	       std::is_convertible<const G&, E>
+	       > = false>
+    constexpr expected (const unexpected<G> &e)
+      : storage (detail::exp::in_unex, std::forward<const G&> (e.error ()))
+    {}
+
+    template<typename G,
+	     G_Requires<
+	       // Constraints:
+	       std::is_constructible<E, const G&>,
+
+	       // Explicit:
+	       not_<std::is_convertible<const G&, E>>
+	       > = false>
+    constexpr explicit expected (const unexpected<G> &e)
+      : storage (detail::exp::in_unex, std::forward<const G&> (e.error ()))
+    {}
+
+    template<typename G,
+	     G_Requires<
+	       // Constraints:
+	       std::is_constructible<E, G&&>,
+
+	       // !Explicit:
+	       std::is_convertible<G&&, E>
+	       > = false>
+    constexpr expected (unexpected<G> &&e)
+      : storage (detail::exp::in_unex, std::forward<G&&> (e.error ()))
+    {}
+
+    template<typename G,
+	     G_Requires<
+	       // Constraints:
+	       std::is_constructible<E, G&&>,
+
+	       // Explicit:
+	       not_<std::is_convertible<G&&, E>>
+	       > = false>
+    constexpr explicit expected (unexpected<G> &&e)
+      : storage (detail::exp::in_unex, std::forward<G&&> (e.error ()))
+    {}
+
+    // [expected.object.cons]p32
+    template<typename... Args,
+	     // good_storage<T> makes the constraint pass only for an empty arg
+	     // list if void.
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, Args...>
+	       > = false>
+    constexpr explicit expected (in_place_t, Args&&... args)
+      : storage (detail::exp::in_value, std::forward<Args> (args)...)
+    {}
+
+    // [expected.object.cons]p36
+    template<typename U, typename... Args,
+	     // good_storage<T> makes the constraint pass only for an empty arg
+	     // list if void.
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_,
+				     std::initializer_list<U>&, Args...>
+	       > = false>
+    constexpr explicit expected (in_place_t, std::initializer_list<U> il,
+				 Args&&... args)
+      : storage (detail::exp::in_value, il, std::forward<Args> (args)...)
+    {}
+
+    // [expected.object.cons]p40
+    template<typename... Args,
+	     G_Requires<
+	       std::is_constructible<E, Args...>
+	       > = false>
+    constexpr explicit expected (unexpect_t, Args&&... args)
+      : storage (detail::exp::in_unex, std::forward<Args> (args)...)
+    {}
+
+    // [expected.object.cons]p44
+    template<typename U, typename... Args,
+	     G_Requires<
+	       std::is_constructible<E, std::initializer_list<U>&, Args...>
+	       > = false>
+    constexpr explicit expected (unexpect_t, std::initializer_list<U> il,
+				 Args&&... args)
+      : storage (detail::exp::in_unex, il, std::forward<Args> (args)...)
+    {}
+
+    // [expected.void.cons]p12
+    template<typename U, typename G,
+	     typename T_ = T,
+	     G_Requires<
+	       // Part of void specialization.
+	       std::is_void<T_>,
+	       // Constraints:
+	       std::is_void<U>,
+	       std::is_constructible<E, const G&>,
+	       not_<g_cons_from_expected<U, G>>,
+
+	       // !Explicit:
+	       std::is_convertible<const G&, E>
+	       > = false>
+    constexpr expected (const expected<U, G>& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->m_has_value = true;
+      else
+	this->construct_unex (rhs.error ());
+    }
+
+    template<typename U, typename G,
+	     typename T_ = T,
+	     G_Requires<
+	       // Part of void specialization.
+	       std::is_void<T_>,
+	       // Constraints:
+	       std::is_void<U>,
+	       std::is_constructible<E, const G&>,
+	       not_<g_cons_from_expected<U, G>>,
+
+	       // Explicit:
+	       not_<std::is_convertible<const G&, E>>
+	       > = false>
+    constexpr explicit expected (const expected<U, G>& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->m_has_value = true;
+      else
+	this->construct_unex (rhs.error ());
+    }
+
+    template<typename U, typename G,
+	     typename T_ = T,
+	     G_Requires<
+	       // Part of void specialization.
+	       std::is_void<T_>,
+	       // Constraints:
+	       std::is_void<U>,
+	       std::is_constructible<E, G&&>,
+	       not_<g_cons_from_expected<U, G>>,
+
+	       // !Explicit:
+	       std::is_convertible<G, E>
+	       > = false>
+    constexpr expected (expected<U, G>&& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->m_has_value = true;
+      else
+	this->construct_unex (std::move (rhs.m_unex));
+    }
+
+    template<typename U, typename G,
+	     typename T_ = T,
+	     G_Requires<
+	       // Part of void specialization.
+	       std::is_void<T_>,
+	       // Constraints:
+	       std::is_void<U>,
+	       std::is_constructible<E, G &&>,
+	       not_<g_cons_from_expected<U, G>>,
+
+	       // Explicit:
+	       not_<std::is_convertible<G, E>>
+	       > = false>
+    constexpr explicit expected (expected<U, G>&& rhs)
+      : storage (detail::exp::in_unused)
+    {
+      if (rhs.has_value ())
+	this->m_has_value = true;
+      else
+	this->construct_unex (std::move (rhs.m_unex));
+    }
+
+    // [expected.object.dtor], implemented in storage
+    ~expected() = default;
+
+    // [expected.object.assign]
+    // The move/copy assignment operators are in the base class, and
+    // constrained by G_Enable_copy_move, much like the constructors.
+    expected &
+    operator= (const expected &) = default;
+    expected &
+    operator= (expected &&) = default;
+
+    // [expected.object.assign]p11
+    template<typename U = std::remove_cv_t<T>,
+	     // Remove overload from T=void expecteds.
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       not_<std::is_same<expected, g_remove_cvref_t<U>>>,
+	       not_<detail::exp::is_unexpected<g_remove_cvref_t<U>>>,
+	       std::is_constructible<T_, U>,
+	       std::is_assignable<T_&, U>,
+
+	       or_<std::is_nothrow_constructible<T_, U>,
+		   std::is_nothrow_move_constructible<T>,
+		   std::is_nothrow_move_constructible<E>>
+	       > = false>
+    GCC_BACKPORT20_CONSTEXPR expected& operator= (U&& v)
+    {
+      this->assign_value (std::forward<U> (v));
+      return *this;
+    }
+
+    // [expected.object.assign]p14
+    template<typename G,
+	     G_Requires<
+	       std::is_constructible<E, const G &>,
+	       std::is_assignable<E&, const G &>,
+
+	       or_<std::is_nothrow_constructible<E, const G &>,
+		   detail::exp::trait_and_nonvoid<
+		     std::is_nothrow_move_constructible, T
+		     >,
+		   std::is_nothrow_move_constructible<E>>
+	       > = false>
+    GCC_BACKPORT20_CONSTEXPR expected &
+    operator= (const unexpected<G>& e)
+    {
+      this->assign_unex (std::forward<const G &> (e.error ()));
+      return *this;
+    }
+
+    template<typename G,
+	     G_Requires<
+	       std::is_constructible<E, G &&>,
+	       std::is_assignable<E&, G &&>,
+
+	       or_<std::is_nothrow_constructible<E, G &&>,
+		   detail::exp::trait_and_nonvoid<
+		     std::is_nothrow_move_constructible, T
+		     >,
+		   std::is_nothrow_move_constructible<E>>
+	       > = false>
+    GCC_BACKPORT20_CONSTEXPR expected &
+    operator= (unexpected<G>&& e)
+    {
+      this->assign_unex (std::forward<G &&> (e.error ()));
+      return *this;
+    }
+
+    // [expected.object.assign]p18
+    template<typename... Args,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_nothrow_constructible<Non_void<T_>, Args...>
+	       > = false>
+    constexpr Non_void<T_> &
+    emplace (Args&&... args) noexcept
+    {
+      this->clear_storage ();
+      this->m_has_value = true;
+      return *gcc::construct_at (std::addressof (this->m_value),
+				 std::forward<Args> (args)...);
+    }
+
+    // [expected.object.assign]p20
+    template<typename U, typename... Args,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_nothrow_constructible<Non_void<T_>,
+					     std::initializer_list<U>&,
+					     Args...>
+	       > = false>
+    constexpr Non_void<T_> &
+    emplace (std::initializer_list<U> il, Args&&... args) noexcept
+    {
+      this->clear_storage ();
+      this->m_has_value = true;
+      return *gcc::construct_at (std::addressof (this->m_value),
+				 il, std::forward<Args> (args)...);
+    }
+
+    // [expected.void.assign]p14
+    template<typename T_ = T>
+    constexpr Only_void<T_>
+    emplace () noexcept
+    {
+      this->clear_storage ();
+      this->m_has_value = true;
+    }
+
+    // [expected.object.swap]
+    template<typename T_ = T, typename E_ = E>
+    constexpr Constrain_swap<T_, E_>
+    swap (expected& rhs)
+      noexcept (and_<std::is_nothrow_move_constructible<T>,
+		     g_is_nothrow_swappable<T>,
+		     std::is_nothrow_move_constructible<E>,
+		     g_is_nothrow_swappable<E>>::value)
+    { this->_swap (static_cast<storage &> (rhs)); }
+
+    template<typename T_ = T, typename E_ = E>
+    friend constexpr
+    Constrain_swap<T_, E_>
+    swap(expected& x, expected& y) noexcept (noexcept(x.swap (y)))
+    { x.swap (y); }
+
+    // [expected.object.monadic] & [expected.void.monadic]
+
+    // [expected.object.monadic]p1
+    template<typename F,
+	     typename E_ = E,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &>
+	       > = false,
+	     typename T_ = T,
+	     Require_non_void<T_> = false>
+    constexpr auto
+    and_then (F &&f) &
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F, decltype ((this->m_value))>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f), this->m_value);
+      else
+	return U (unexpect, this->m_unex);
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &>
+	       > = false,
+	     typename T_ = T,
+	     Require_non_void<T_> = false>
+    constexpr auto
+    and_then (F &&f) const &
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F, decltype ((this->m_value))>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f), this->m_value);
+      else
+	return U (unexpect, this->m_unex);
+    }
+
+    // [expected.object.monadic]p5
+    template<typename F,
+	     typename E_ = E,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &&>
+	       > = false,
+	     typename T_ = T,
+	     Require_non_void<T_> = false>
+    constexpr auto
+    and_then (F &&f) &&
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F, decltype (std::move (this->m_value))>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f), std::move (this->m_value));
+      else
+	return U (unexpect, std::move (this->m_unex));
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &&>
+	       > = false,
+	     typename T_ = T,
+	     Require_non_void<T_> = false>
+    constexpr auto
+    and_then (F &&f) const &&
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F, decltype (std::move (this->m_value))>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f), std::move (this->m_value));
+      else
+	return U (unexpect, std::move (this->m_unex));
+    }
+
+    // [expected.void.monadic]
+
+    // [expected.void.monadic]p1
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    and_then (F &&f) &
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f));
+      else
+	return U (unexpect, this->m_unex);
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    and_then (F &&f) const &
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f));
+      else
+	return U (unexpect, this->m_unex);
+    }
+
+    // [expected.void.monadic]p5
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &&>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    and_then (F &&f) &&
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f));
+      else
+	return U (unexpect, std::move (this->m_unex));
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &&>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    and_then (F &&f) const &&
+    {
+      using U = g_remove_cvref_t<g_invoke_result_t<F>>;
+      static_assert (detail::exp::is_expected_with_same_error<U, E>::value,
+		     "the function passed to std::expected<T, E>::and_then "
+		     "must return a std::expected with same error type");
+      if (has_value ())
+	return gcc::invoke (std::forward<F> (f));
+      else
+	return U (unexpect, std::move (this->m_unex));
+    }
+
+    // [expected.object.monadic]p9
+
+    // The good_storage<T> type will, for void, make the constraint always
+    // pass.
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, T_ &>
+	       > = false>
+    constexpr auto
+    or_else (F &&f) &
+    {
+      using G = g_remove_cvref_t<g_invoke_result_t<F, decltype (error ())>>;
+      static_assert (detail::exp::is_expected_with_same_value<G, T>::value,
+		     "the function passed to std::expected<T, E>::or_else "
+		     "must return a std::expected with same value type");
+      if (has_value ())
+	return G (in_place, this->m_value);
+      else
+	return gcc::invoke (std::forward<F> (f), this->m_unex);
+    }
+
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, const T_&>
+	       > = false>
+    constexpr auto
+    or_else (F &&f) const &
+    {
+      using G = g_remove_cvref_t<g_invoke_result_t<F, decltype (error ())>>;
+      static_assert (detail::exp::is_expected_with_same_value<G, T>::value,
+		     "the function passed to std::expected<T, E>::or_else "
+		     "must return a std::expected with same value type");
+      if (has_value ())
+	return G (in_place, this->m_value);
+      else
+	return gcc::invoke (std::forward<F> (f), this->m_unex);
+    }
+
+    // [expected.object.monadic]p13
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, T_ &&>
+	       > = false>
+    constexpr auto
+    or_else (F &&f) &&
+    {
+      using G = g_remove_cvref_t<g_invoke_result_t<F, decltype (std::move (error ()))>>;
+      static_assert (detail::exp::is_expected_with_same_value<G, T>::value,
+		     "the function passed to std::expected<T, E>::or_else "
+		     "must return a std::expected with same value type");
+      if (has_value ())
+	return G (in_place, std::move (this->m_value));
+      else
+	return gcc::invoke (std::forward<F> (f), std::move (this->m_unex));
+    }
+
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, const T_ &&>
+	       > = false>
+    constexpr auto
+    or_else (F &&f) const &&
+    {
+      using G = g_remove_cvref_t<g_invoke_result_t<F, decltype (std::move (error ()))>>;
+      static_assert (detail::exp::is_expected_with_same_value<G, T>::value,
+		     "the function passed to std::expected<T, E>::or_else "
+		     "must return a std::expected with same value type");
+      if (has_value ())
+	return G (in_place, std::move (this->m_value));
+      else
+	return gcc::invoke (std::forward<F> (f), std::move (this->m_unex));
+    }
+
+    // [expected.object.monadic]p17
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &>
+	       > = false>
+    constexpr auto
+    transform (F &&f) &
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F, decltype ((this->m_value))>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f), this->m_value);
+	});
+      else
+	return Res (unexpect, this->m_unex);
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &>
+	       > = false>
+    constexpr auto
+    transform (F &&f) const &
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F, decltype ((this->m_value))>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f), this->m_value);
+	});
+      else
+	return Res (unexpect, this->m_unex);
+    }
+
+    // [expected.object.monadic]p21
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &&>
+	       > = false>
+    constexpr auto
+    transform (F &&f) &&
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F, decltype (std::move (this->m_value))>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f), std::move (this->m_value));
+	});
+      else
+	return Res (unexpect, std::move (this->m_unex));
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     Require_non_void<T_> = false,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &&>
+	       > = false>
+    constexpr auto
+    transform (F &&f) const &&
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F, decltype (std::move (this->m_value))>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f), std::move (this->m_value));
+	});
+      else
+	return Res (unexpect, std::move (this->m_unex));
+    }
+
+    // [expected.void.monadic]p15
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    transform (F &&f) &
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f));
+	});
+      else
+	return Res (unexpect, this->m_unex);
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    transform (F &&f) const &
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f));
+	});
+      else
+	return Res (unexpect, this->m_unex);
+    }
+
+    // [expected.void.monadic]p19
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, E_ &&>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    transform (F &&f) &&
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f));
+	});
+      else
+	return Res (unexpect, std::move (this->m_unex));
+    }
+
+    template<typename F,
+	     typename E_ = E,
+	     typename T_ = T,
+	     G_Requires<
+	       std::is_constructible<E_, const E_ &&>,
+	       std::is_void<T_>
+	       > = false>
+    constexpr auto
+    transform (F &&f) const &&
+    {
+      using U = std::remove_cv_t<g_invoke_result_t<F>>;
+      using Res = expected<U, E>;
+      if (has_value ())
+	return Res (detail::exp::in_place_inv{}, [&] () {
+	  return gcc::invoke (std::forward<F> (f));
+	});
+      else
+	return Res (unexpect, std::move (this->m_unex));
+    }
+
+    // [expected.object.monadic]p25
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, T_ &>
+	       > = false>
+    constexpr auto
+    transform_error (F &&f) &
+    {
+      using G = std::remove_cv_t<g_invoke_result_t<F, decltype (error ())>>;
+      using Res = expected<T, G>;
+      if (has_value ())
+	return Res (in_place, this->m_value);
+      else
+	return Res (detail::exp::unexpect_inv{}, [&] () {
+	  return gcc::invoke(std::forward<F> (f), this->m_unex);
+	});
+    }
+
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, const T_ &>
+	       > = false>
+    constexpr auto
+    transform_error (F &&f) const &
+    {
+      using G = std::remove_cv_t<g_invoke_result_t<F, decltype (error ())>>;
+      using Res = expected<T, G>;
+      if (has_value ())
+	return Res (in_place, this->m_value);
+      else
+	return Res (detail::exp::unexpect_inv{}, [&] () {
+	  return gcc::invoke(std::forward<F> (f), this->m_unex);
+	});
+    }
+
+    // [expected.object.monadic]p29
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, T_ &&>
+	       > = false>
+    constexpr auto
+    transform_error (F &&f) &&
+    {
+      using G = std::remove_cv_t<g_invoke_result_t<F, decltype (std::move (error ()))>>;
+      using Res = expected<T, G>;
+      if (has_value ())
+	return Res (in_place, std::move (this->m_value));
+      else
+	return Res (detail::exp::unexpect_inv{}, [&] () {
+	  return gcc::invoke(std::forward<F> (f), std::move (this->m_unex));
+	});
+    }
+
+    template<typename F,
+	     typename T_ = detail::exp::good_storage<T>,
+	     G_Requires<
+	       std::is_constructible<T_, const T_ &&>
+	       > = false>
+    constexpr auto
+    transform_error (F &&f) const &&
+    {
+      using G = std::remove_cv_t<g_invoke_result_t<F, decltype (std::move (error ()))>>;
+      using Res = expected<T, G>;
+      if (has_value ())
+	return Res (in_place, std::move (this->m_value));
+      else
+	return Res (detail::exp::unexpect_inv{}, [&] () {
+	  return gcc::invoke(std::forward<F> (f), std::move (this->m_unex));
+	});
+    }
+
+    // [expected.object.eq]
+    template<typename T2, typename E2,
+	     typename T_ = T>
+    [[nodiscard]] friend constexpr
+    detail::exp::eql_2_return_t<Non_void<T_>, Non_void<T2>, E, E2>
+    operator== (const expected &x, const expected<T2, E2> &y)
+    {
+      if (x.m_has_value && y.m_has_value)
+	return x.m_value == y.m_value;
+      else if (!x.m_has_value && !y.m_has_value)
+	return x.m_unex == y.m_unex;
+      return false;
+    }
+
+    template<typename T2,
+	     G_Requires<
+	       not_<detail::exp::is_expected<T2>>
+	       > = false,
+	     typename T_ = T>
+    [[nodiscard]] friend constexpr
+    eql_return_t<Non_void<T_>, T2>
+    operator== (const expected &x, const T2 &y)
+    {
+      if (!x.m_has_value)
+	return false;
+      return x.m_value == y;
+    }
+
+    template<typename E2>
+    [[nodiscard]] friend constexpr
+    eql_return_t<E, E2>
+    operator== (const expected &x, const unexpected<E2> &y)
+    {
+      if (x.m_has_value)
+	return false;
+      return x.m_unex == y.unex;
+    }
+
+    // [expected.void.eq]
+    template<typename T2, typename E2,
+	     G_Requires<std::is_void<T2>> = false,
+	     typename T_ = T,
+	     G_Requires<std::is_void<T_>> = false>
+    [[nodiscard]] friend constexpr
+    eql_return_t<E, E2>
+    operator== (const expected &x, const expected<T2, E2> &y)
+    {
+      if (x.m_has_value && y.m_has_value)
+	return true;
+      else if (!x.m_has_value && !y.m_has_value)
+	return x.m_unex == y.m_unex;
+      return false;
+    }
+
+  private:
+    template<typename Fn>
+    explicit constexpr
+    expected (detail::exp::in_place_inv tag, Fn&& fn)
+      : storage (tag, std::forward<Fn> (fn))
+    {}
+
+    template<typename Fn>
+    explicit constexpr
+    expected(detail::exp::unexpect_inv tag, Fn&& fn)
+      : storage (tag, std::forward<Fn> (fn))
+    {}
+
+    template<typename, typename>
+    friend struct expected;
+  };
+
+  // Inequality operators.
+  template<typename T1, typename E1, typename T2, typename E2>
+  [[nodiscard]] constexpr eql_return_t<expected<T1, E1>, expected<T2, E2>>
+  operator!= (const expected<T1, E1>& x, const expected<T2, E2>& y)
+  { return !(x == y); }
+
+  template<typename T1, typename E1, typename T2>
+  [[nodiscard]] constexpr eql_return_t<expected<T1, E1>, T2>
+  operator!= (const expected<T1, E1>& x, const T2& y)
+  { return !(x == y); }
+
+  template<typename T1, typename E1, typename E2>
+  [[nodiscard]] constexpr eql_return_t<expected<T1, E1>, unexpected<E2>>
+  operator!= (const expected<T1, E1>& x, const unexpected<E2>& y)
+  { return !(x == y); }
+
+  template<typename E1, typename E2>
+  [[nodiscard]] constexpr eql_return_t<unexpected<E1>, unexpected<E2>>
+  operator!= (const unexpected<E1>& x, const unexpected<E2>& y)
+  { return !(x == y); }
+} // namespace gcc
+
+#endif // GCC_EXPECTED
diff --git a/gcc/stdbackport/expectedfwd b/gcc/stdbackport/expectedfwd
new file mode 100644
index 000000000000..314df4846ae7
--- /dev/null
+++ b/gcc/stdbackport/expectedfwd
@@ -0,0 +1,31 @@
+/* Forward declarations for expected for -*- C++ -*- 14.
+   Copyright (C) 2026 The GNU Toolchain Authors.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_EXPECTEDFWD
+#define GCC_EXPECTEDFWD 1
+
+namespace gcc {
+  template<typename E>
+  struct unexpected;
+
+  template<typename T, typename E>
+  struct [[nodiscard]] expected;
+} // namespace gcc
+
+#endif // GCC_EXPECTEDFWD
diff --git a/gcc/stdbackport/gbits/assert.h b/gcc/stdbackport/gbits/assert.h
new file mode 100644
index 000000000000..1e3f95b878de
--- /dev/null
+++ b/gcc/stdbackport/gbits/assert.h
@@ -0,0 +1,29 @@
+/* Configurable assert.  -*- C++ -*-
+   Copyright (C) 2026 The GNU Toolchain Authors.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#ifndef GCC_BACKPORT_ASSERT_H
+#define GCC_BACKPORT_ASSERT_H 1
+
+/* Useful to override if running testsuites.  */
+#ifndef gccbackport_assert
+# define gccbackport_assert(x) gcc_assert (x)
+#endif
+
+#endif // GCC_BACKPORT_ASSERT_H
diff --git a/gcc/stdbackport/gbits/check_system_h.h b/gcc/stdbackport/gbits/check_system_h.h
new file mode 100644
index 000000000000..44d53ef9efde
--- /dev/null
+++ b/gcc/stdbackport/gbits/check_system_h.h
@@ -0,0 +1,31 @@
+/* Verify that prerequisites of files including this header have been included
+   through system.h.
+   Copyright (C) 2026 The GNU Toolchain Authors.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#ifdef WANT_FUNCTIONAL
+# include <functional>
+# ifndef INCLUDE_FUNCTIONAL
+#  ifdef GCC_SYSTEM_H
+#   warning "<functional> included after system.h.  " \
+   "Please define INCLUDE_FUNCTIONAL before including system.h"
+#  endif
+# endif
+# undef WANT_FUNCTIONAL
+#endif
diff --git a/gcc/stdbackport/gbits/enable_special_members.h b/gcc/stdbackport/gbits/enable_special_members.h
new file mode 100644
index 000000000000..7704f4f3ceea
--- /dev/null
+++ b/gcc/stdbackport/gbits/enable_special_members.h
@@ -0,0 +1,310 @@
+// <bits/enable_special_members.h> -*- C++ -*-
+
+// Copyright (C) 2013-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/enable_special_members.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly.
+ */
+
+#ifndef GCC_BACKPORT_ENABLE_SPECIAL_MEMBERS_H
+#define GCC_BACKPORT_ENABLE_SPECIAL_MEMBERS_H 1
+
+namespace gcc
+{
+/// @cond undocumented
+
+  struct G_Enable_default_constructor_tag
+  {
+    explicit constexpr G_Enable_default_constructor_tag() = default;
+  };
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the default
+  * constructor.
+  * @sa _Enable_special_members
+  */
+template<bool G_Switch, typename G_Tag = void>
+  struct G_Enable_default_constructor
+  {
+    constexpr G_Enable_default_constructor() noexcept = default;
+    constexpr G_Enable_default_constructor(G_Enable_default_constructor const&)
+      noexcept  = default;
+    constexpr G_Enable_default_constructor(G_Enable_default_constructor&&)
+      noexcept = default;
+    G_Enable_default_constructor&
+    operator=(G_Enable_default_constructor const&) noexcept = default;
+    G_Enable_default_constructor&
+    operator=(G_Enable_default_constructor&&) noexcept = default;
+
+    // Can be used in other ctors.
+    constexpr explicit
+    G_Enable_default_constructor(G_Enable_default_constructor_tag) { }
+  };
+
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the default
+  * destructor.
+  * @sa _Enable_special_members
+  */
+template<bool G_Switch, typename G_Tag = void>
+  struct G_Enable_destructor { };
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the copy/move
+  * special members.
+  * @sa _Enable_special_members
+  */
+template<bool G_Copy, bool G_CopyAssignment,
+         bool G_Move, bool G_MoveAssignment,
+         typename G_Tag = void>
+  struct G_Enable_copy_move { };
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the special
+  * members.
+  *
+  * The @c _Tag type parameter is to make mixin bases unique and thus avoid
+  * ambiguities.
+  */
+template<bool G_Default, bool G_Destructor,
+         bool G_Copy, bool G_CopyAssignment,
+         bool G_Move, bool G_MoveAssignment,
+         typename G_Tag = void>
+  struct G_Enable_special_members
+  : private G_Enable_default_constructor<G_Default, G_Tag>,
+    private G_Enable_destructor<G_Destructor, G_Tag>,
+    private G_Enable_copy_move<G_Copy, G_CopyAssignment,
+                              G_Move, G_MoveAssignment,
+                              G_Tag>
+  { };
+
+// Boilerplate follows.
+
+template<typename G_Tag>
+  struct G_Enable_default_constructor<false, G_Tag>
+  {
+    constexpr G_Enable_default_constructor() noexcept = delete;
+    constexpr G_Enable_default_constructor(G_Enable_default_constructor const&)
+      noexcept  = default;
+    constexpr G_Enable_default_constructor(G_Enable_default_constructor&&)
+      noexcept = default;
+    G_Enable_default_constructor&
+    operator=(G_Enable_default_constructor const&) noexcept = default;
+    G_Enable_default_constructor&
+    operator=(G_Enable_default_constructor&&) noexcept = default;
+
+    // Can be used in other ctors.
+    constexpr explicit
+    G_Enable_default_constructor(G_Enable_default_constructor_tag) { }
+  };
+
+template<typename G_Tag>
+  struct G_Enable_destructor<false, G_Tag>
+  { ~G_Enable_destructor() noexcept = delete; };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, true, true, true, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<true, false, true, true, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, false, true, true, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<true, true, false, true, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, true, false, true, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<true, false, false, true, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, false, false, true, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<true, true, true, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, true, true, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<true, false, true, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, false, true, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<true, true, false, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, true, false, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = default;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<true, false, false, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename G_Tag>
+  struct G_Enable_copy_move<false, false, false, false, G_Tag>
+  {
+    constexpr G_Enable_copy_move() noexcept                          = default;
+    constexpr G_Enable_copy_move(G_Enable_copy_move const&) noexcept  = delete;
+    constexpr G_Enable_copy_move(G_Enable_copy_move&&) noexcept       = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move const&) noexcept                    = delete;
+    G_Enable_copy_move&
+    operator=(G_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+/// @endcond
+} // namespace gcc
+
+#endif // GCC_BACKPORT_ENABLE_SPECIAL_MEMBERS_H
diff --git a/gcc/stdbackport/gbits/exception_defines.h b/gcc/stdbackport/gbits/exception_defines.h
new file mode 100644
index 000000000000..8650ea7c1300
--- /dev/null
+++ b/gcc/stdbackport/gbits/exception_defines.h
@@ -0,0 +1,53 @@
+// -fno-exceptions Support -*- C++ -*-
+
+// Copyright (C) 2001-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/exception_defines.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{exception}
+ */
+
+#ifndef GCC_BACKPORT_EXCEPTION_DEFINES_H
+#define GCC_BACKPORT_EXCEPTION_DEFINES_H 1
+
+#include "assert.h"
+
+#if !defined(GCC_BACKPORT_WANT_EXCEPTIONS) || !__cpp_exceptions
+// Iff exceptions unwanted, transform error handling code to work without it.
+# define GCC_BACKPORT_HAS_EXCEPTIONS 0
+# define g_try      if (true)
+# define g_catch(X) if (false)
+# define g_throw_exception_again
+// Note that when exceptions are disabled, EXC is neither evaluated *nor used*.
+# define g_throw_or_abort(exc) gccbackport_assert (!#exc)
+#else
+// Else proceed normally.
+# define GCC_BACKPORT_HAS_EXCEPTIONS 1
+# define g_try      try
+# define g_catch(X) catch(X)
+# define g_throw_exception_again throw
+// Note that when exceptions are disabled, EXC is neither evaluated *nor used*.
+# define g_throw_or_abort(exc) throw (exc)
+#endif
+
+#endif
diff --git a/gcc/stdbackport/gbits/extras.h b/gcc/stdbackport/gbits/extras.h
new file mode 100644
index 000000000000..83845294606c
--- /dev/null
+++ b/gcc/stdbackport/gbits/extras.h
@@ -0,0 +1,56 @@
+// A few more utilities used in the backports not corresponding to existing headers -*- C++ -*-
+
+// Copyright (C) 2026 Free Software Foundation, Inc.
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef GCC_BACKPORT_BITS_CONDITIONALS_H
+#define GCC_BACKPORT_BITS_CONDITIONALS_H 1
+
+#include <type_traits>
+
+#ifndef __has_builtin
+# define gcc_backport_has_builtin(x) 0
+#else
+# define gcc_backport_has_builtin(x) __has_builtin (x)
+#endif
+
+// Helper.  Expands to 'constexpr' in C++20 and an empty string otherwise.
+#if __cplusplus >= 202002L
+# define GCC_BACKPORT20_CONSTEXPR constexpr
+#else
+# define GCC_BACKPORT20_CONSTEXPR
+#endif
+
+namespace gcc
+{
+  template<typename G_Tp>
+    [[nodiscard]]
+    constexpr std::add_const_t<G_Tp>&
+    as_const(G_Tp& g_t) noexcept
+    { return g_t; }
+
+  template<typename G_Tp>
+    void as_const(const G_Tp&&) = delete;
+} // namespace gcc
+
+#endif // GCC_BACKPORT_BITS_CONDITIONALS_H
diff --git a/gcc/stdbackport/gbits/functional_hash.h b/gcc/stdbackport/gbits/functional_hash.h
new file mode 100644
index 000000000000..a5edc2e4a36d
--- /dev/null
+++ b/gcc/stdbackport/gbits/functional_hash.h
@@ -0,0 +1,60 @@
+// functional_hash.h header but gutted -*- C++ -*-
+
+// Copyright (C) 2007-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/functional_hash.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef GCC_BACKPORT_FUNCTIONAL_HASH_H
+#define GCC_BACKPORT_FUNCTIONAL_HASH_H 1
+
+#define WANT_FUNCTIONAL
+#include "check_system_h.h"
+
+#include <type_traits>
+
+#include "more_type_traits.h"
+
+namespace gcc
+{
+  template<typename G_Tp, typename = void>
+    struct g_is_hash_enabled_for : std::false_type {};
+
+  template<typename G_Tp>
+    struct
+    g_is_hash_enabled_for<G_Tp,
+			  void_t<decltype(std::hash<G_Tp>()(std::declval<G_Tp>()))>>
+    : std::true_type {};
+
+  // Helper struct for defining disabled specializations of std::hash.
+  template<typename G_Tp>
+    struct g_hash_not_enabled
+    {
+      g_hash_not_enabled(g_hash_not_enabled&&) = delete;
+      ~g_hash_not_enabled() = delete;
+    };
+} // namespace
+
+#endif // GCC_BACKPORT_FUNCTIONAL_HASH_H
diff --git a/gcc/stdbackport/gbits/inplace_tags.h b/gcc/stdbackport/gbits/inplace_tags.h
new file mode 100644
index 000000000000..defb430fb773
--- /dev/null
+++ b/gcc/stdbackport/gbits/inplace_tags.h
@@ -0,0 +1,58 @@
+// Tag types for inplace construction. -*- C++ -*-
+
+// Copyright (C) 2004-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/bits/inplace_tags.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{utility}
+ *
+ *  This file contains the parts of `<utility>` needed by other headers,
+ *  so they don't need to include the whole of `<utility>`.
+ */
+
+#ifndef GCC_BACKPORT_GLIBCXX_INPLACE_TAGS_H
+#define GCC_BACKPORT_GLIBCXX_INPLACE_TAGS_H 1
+
+#if __cplusplus >= 201703L
+# include <utility>
+#endif
+#include "more_type_traits.h"
+
+namespace gcc
+{
+#if __cplusplus >= 201703L // C++17
+  using std::in_place_t;
+  using std::in_place;
+#else // !C++17
+  struct in_place_t {
+    explicit in_place_t() = default;
+  };
+
+  static constexpr in_place_t in_place{};
+#endif // !C++17
+
+  template<typename T>
+  using is_in_place = std::is_same<g_remove_cvref_t<T>, in_place_t>;
+} // namespace gcc
+
+#endif /* GCC_BACKPORT_GLIBCXX_INPLACE_TAGS_H */
diff --git a/gcc/stdbackport/gbits/invoke.h b/gcc/stdbackport/gbits/invoke.h
new file mode 100644
index 000000000000..1eae4264b544
--- /dev/null
+++ b/gcc/stdbackport/gbits/invoke.h
@@ -0,0 +1,132 @@
+// Implementation of INVOKE -*- C++ -*-
+
+// Copyright (C) 2016-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/bits/invoke.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef GCC_BACKPORT_GLIBCXX_INVOKE_H
+#define GCC_BACKPORT_GLIBCXX_INVOKE_H 1
+
+#include <type_traits>
+#include <utility>
+
+#include "more_type_traits.h"
+
+namespace gcc
+{
+
+  /**
+   *  @addtogroup utilities
+   *  @{
+   */
+
+  // Used by __invoke_impl instead of std::forward<_Tp> so that a
+  // reference_wrapper is converted to an lvalue-reference.
+  template<typename G_Tp, typename G_Up = typename g_inv_unwrap<G_Tp>::type>
+    constexpr G_Up&&
+    g_invfwd(typename std::remove_reference<G_Tp>::type& g_t) noexcept
+    { return static_cast<G_Up&&>(g_t); }
+
+  template<typename G_Res, typename G_Fn, typename... G_Args>
+    constexpr G_Res
+    g_invoke_impl(g_invoke_other, G_Fn&& g_f, G_Args&&... g_args)
+    { return std::forward<G_Fn>(g_f)(std::forward<G_Args>(g_args)...); }
+
+  template<typename G_Res, typename G_MemFun, typename G_Tp, typename... G_Args>
+    constexpr G_Res
+    g_invoke_impl(g_invoke_memfun_ref, G_MemFun&& g_f, G_Tp&& g_t,
+		  G_Args&&... g_args)
+    { return (g_invfwd<G_Tp>(g_t).*g_f)(std::forward<G_Args>(g_args)...); }
+
+  template<typename G_Res, typename G_MemFun, typename G_Tp, typename... G_Args>
+    constexpr G_Res
+    g_invoke_impl(g_invoke_memfun_deref, G_MemFun&& g_f, G_Tp&& g_t,
+		  G_Args&&... g_args)
+    {
+      return ((*std::forward<G_Tp>(g_t)).*g_f)(std::forward<G_Args>(g_args)...);
+    }
+
+  template<typename G_Res, typename G_MemPtr, typename G_Tp>
+    constexpr G_Res
+    g_invoke_impl(g_invoke_memobj_ref, G_MemPtr&& g_f, G_Tp&& g_t)
+    { return g_invfwd<G_Tp>(g_t).*g_f; }
+
+  template<typename G_Res, typename G_MemPtr, typename G_Tp>
+    constexpr G_Res
+    g_invoke_impl(g_invoke_memobj_deref, G_MemPtr&& g_f, G_Tp&& g_t)
+    { return (*std::forward<G_Tp>(g_t)).*g_f; }
+
+  /// Invoke a callable object.
+  template<typename G_Callable, typename... G_Args>
+    constexpr typename g_invoke_result<G_Callable, G_Args...>::type
+    invoke(G_Callable&& g_fn, G_Args&&... g_args)
+    noexcept(g_is_nothrow_invocable<G_Callable, G_Args...>::value)
+    {
+      using g_result = g_invoke_result<G_Callable, G_Args...>;
+      using g_type = typename g_result::type;
+      using g_tag = typename g_result::g_invoke_type;
+      return gcc::g_invoke_impl<g_type>(g_tag{}, std::forward<G_Callable>(g_fn),
+					std::forward<G_Args>(g_args)...);
+    }
+
+//   // This is a non-SFINAE-friendly std::invoke_r<R>(fn, args...) for C++11/14.
+//   // It's used in std::function, std::bind, and std::packaged_task. Only
+//   // std::function is constrained on is_invocable_r, but that is checked on
+//   // construction so doesn't need to be checked again when calling __invoke_r.
+//   // Consequently, these __invoke_r overloads do not check for invocable
+//   // arguments, nor check that the invoke result is convertible to R.
+
+//   // INVOKE<R>: Invoke a callable object and convert the result to R.
+//   template<typename G_Res, typename G_Callable, typename... G_Args>
+//     constexpr std::enable_if_t<!std::is_void<G_Res>::value, G_Res>
+//     g_invoke_r(G_Callable&& g_fn, G_Args&&... g_args)
+//     {
+//       using g_result = g_invoke_result<G_Callable, G_Args...>;
+//       using g_type = typename g_result::type;
+// #if gcc_backport_has_builtin(__reference_converts_from_temporary)
+//       static_assert(!__reference_converts_from_temporary(G_Res, g_type),
+// 		    "INVOKE<R> must not create a dangling reference");
+// #endif
+//       using g_tag = typename g_result::g_invoke_type;
+//       return gcc::g_invoke_impl<g_type>(g_tag{}, std::forward<G_Callable>(g_fn),
+// 					std::forward<G_Args>(g_args)...);
+//     }
+
+//   // INVOKE<R> when R is cv void
+//   template<typename G_Res, typename G_Callable, typename... G_Args>
+//     constexpr std::enable_if_t<std::is_void<G_Res>::value, G_Res>
+//     g_invoke_r(G_Callable&& g_fn, G_Args&&... g_args)
+//     {
+//       using g_result = g_invoke_result<G_Callable, G_Args...>;
+//       using g_type = typename g_result::type;
+//       using g_tag = typename g_result::g_invoke_type;
+//       gcc::g_invoke_impl<g_type>(g_tag{}, std::forward<G_Callable>(g_fn),
+// 				 std::forward<G_Args>(g_args)...);
+//     }
+
+} // namespace gcc
+
+#endif // GCC_BACKPORT_GLIBCXX_INVOKE_H
diff --git a/gcc/stdbackport/gbits/more_type_traits.h b/gcc/stdbackport/gbits/more_type_traits.h
new file mode 100644
index 000000000000..5c34f6ab3db1
--- /dev/null
+++ b/gcc/stdbackport/gbits/more_type_traits.h
@@ -0,0 +1,614 @@
+// Some C++17 <type_traits> in C++14 -*- C++ -*-
+
+// Copyright (C) 2007-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef GCC_BACKPORT_BITS_MORE_TYPE_TRAITS_H
+#define GCC_BACKPORT_BITS_MORE_TYPE_TRAITS_H
+
+#include "extras.h"
+#include <type_traits>
+#include <cstddef>
+
+namespace gcc
+{
+  // std::void_t in C++14.
+  template<typename...>
+    using void_t = void;
+
+  // type_identity in C++14.
+  template <typename _Type>
+    struct g_type_identity
+    { using type = _Type; };
+
+  template<typename _Tp>
+    using g_type_identity_t = typename g_type_identity<_Tp>::type;
+
+  // g_remove_cvref_t (std::remove_cvref_t for C++11).
+  template<typename _Tp>
+    using g_remove_cvref_t
+      = typename std::remove_cv<typename std::remove_reference<_Tp>::type>::type;
+
+  // Conditional helpers.
+
+  namespace detail
+  {
+    // A variadic alias template that resolves to its first argument.
+    template<typename G_Tp, typename...>
+      using first_t = G_Tp;
+
+    // These are deliberately not defined.
+    template<typename... G_Bn>
+      auto or_fn(int) -> first_t<std::false_type,
+				 std::enable_if_t<!bool(G_Bn::value)>...>;
+
+    template<typename... G_Bn>
+      auto or_fn(...) -> std::true_type;
+
+    template<typename... G_Bn>
+      auto and_fn(int) -> first_t<std::true_type,
+				  std::enable_if_t<bool(G_Bn::value)>...>;
+
+    template<typename... G_Bn>
+      auto and_fn(...) -> std::false_type;
+
+    // This does not match what libstdc++ does.  It declares
+    // true_type/false_type in terms of __bool_constant.  But, if we're to
+    // match the standard true_type/false_type, we have to do this.
+    template<bool G_Bn>
+      struct to_bool_trait_;
+    template<> struct to_bool_trait_<true>
+    { using type = std::true_type; };
+    template<> struct to_bool_trait_<false>
+    { using type = std::false_type; };
+
+    template<bool G_Bn>
+    using to_bool_trait = typename to_bool_trait_<G_Bn>::type;
+  } // namespace detail
+
+  // Like C++17 std::dis/conjunction, but usable in C++11 and resolves
+  // to either true_type or false_type which allows for a more efficient
+  // implementation that avoids recursive class template instantiation.
+  template<typename... G_Bn>
+    struct or_
+    : decltype(detail::or_fn<G_Bn...>(0))
+    { };
+
+  template<typename... G_Bn>
+    struct and_
+    : decltype(detail::and_fn<G_Bn...>(0))
+    { };
+
+  template<typename G_Pp>
+    struct not_
+    : detail::to_bool_trait<!bool(G_Pp::value)>
+    { };
+
+  /// @cond undocumented
+  namespace g_swappable_details {
+    using std::swap;
+
+    struct g_do_is_swappable_impl
+    {
+      template<typename G_Tp, typename
+               = decltype(swap(std::declval<G_Tp&>(), std::declval<G_Tp&>()))>
+        static std::true_type g_test(int);
+
+      template<typename>
+        static std::false_type g_test(...);
+    };
+
+    struct g_do_is_nothrow_swappable_impl
+    {
+      template<typename G_Tp>
+        static detail::to_bool_trait<
+          noexcept(swap(std::declval<G_Tp&>(), std::declval<G_Tp&>()))
+        > g_test(int);
+
+      template<typename>
+        static std::false_type g_test(...);
+    };
+
+  } // namespace g_swappable_details
+
+  template<typename G_Tp>
+    struct g_is_swappable_impl
+    : public g_swappable_details::g_do_is_swappable_impl
+    {
+      using type = decltype(g_test<G_Tp>(0));
+    };
+
+  template<typename G_Tp>
+    struct g_is_nothrow_swappable_impl
+    : public g_swappable_details::g_do_is_nothrow_swappable_impl
+    {
+      using type = decltype(g_test<G_Tp>(0));
+    };
+
+  template<typename G_Tp>
+    struct g_is_swappable
+    : public g_is_swappable_impl<G_Tp>::type
+    { };
+
+  template<typename G_Tp>
+    struct g_is_nothrow_swappable
+    : public g_is_nothrow_swappable_impl<G_Tp>::type
+    { };
+
+  // Used by INVOKE.
+  template<typename _Tp>
+    struct g_success_type
+    { using type = _Tp; };
+
+  struct g_failure_type
+  { };
+
+  /// result_of
+  template<typename G_Signature>
+    struct result_of;
+
+  // Sfinae-friendly result_of implementation:
+
+  /// @cond undocumented
+  struct g_invoke_memfun_ref { };
+  struct g_invoke_memfun_deref { };
+  struct g_invoke_memobj_ref { };
+  struct g_invoke_memobj_deref { };
+  struct g_invoke_other { };
+
+  // Associate a tag type with a specialization of __success_type.
+  template<typename G_Tp, typename G_Tag>
+    struct g_result_of_success : g_success_type<G_Tp>
+    { using g_invoke_type = G_Tag; };
+
+  // [func.require] paragraph 1 bullet 1:
+  struct g_result_of_memfun_ref_impl
+  {
+    template<typename G_Fp, typename G_Tp1, typename... G_Args>
+      static g_result_of_success<decltype(
+      (std::declval<G_Tp1>().*std::declval<G_Fp>())(std::declval<G_Args>()...)
+      ), g_invoke_memfun_ref> G_S_test(int);
+
+    template<typename...>
+      static g_failure_type G_S_test(...);
+  };
+
+  template<typename G_MemPtr, typename G_Arg, typename... G_Args>
+    struct g_result_of_memfun_ref
+    : private g_result_of_memfun_ref_impl
+    {
+      using type = decltype(G_S_test<G_MemPtr, G_Arg, G_Args...>(0));
+    };
+
+  // [func.require] paragraph 1 bullet 2:
+  struct g_result_of_memfun_deref_impl
+  {
+    template<typename G_Fp, typename G_Tp1, typename... G_Args>
+      static g_result_of_success<decltype(
+      ((*std::declval<G_Tp1>()).*std::declval<G_Fp>())(std::declval<G_Args>()...)
+      ), g_invoke_memfun_deref> G_S_test(int);
+
+    template<typename...>
+      static g_failure_type G_S_test(...);
+  };
+
+  template<typename G_MemPtr, typename G_Arg, typename... G_Args>
+    struct g_result_of_memfun_deref
+    : private g_result_of_memfun_deref_impl
+    {
+      using type = decltype(G_S_test<G_MemPtr, G_Arg, G_Args...>(0));
+    };
+
+  // [func.require] paragraph 1 bullet 3:
+  struct g_result_of_memobj_ref_impl
+  {
+    template<typename G_Fp, typename G_Tp1>
+      static g_result_of_success<decltype(
+      std::declval<G_Tp1>().*std::declval<G_Fp>()
+      ), g_invoke_memobj_ref> G_S_test(int);
+
+    template<typename, typename>
+      static g_failure_type G_S_test(...);
+  };
+
+  template<typename G_MemPtr, typename G_Arg>
+    struct g_result_of_memobj_ref
+    : private g_result_of_memobj_ref_impl
+    {
+      using type = decltype(G_S_test<G_MemPtr, G_Arg>(0));
+    };
+
+  // [func.require] paragraph 1 bullet 4:
+  struct g_result_of_memobj_deref_impl
+  {
+    template<typename G_Fp, typename G_Tp1>
+      static g_result_of_success<decltype(
+      (*std::declval<G_Tp1>()).*std::declval<G_Fp>()
+      ), g_invoke_memobj_deref> G_S_test(int);
+
+    template<typename, typename>
+      static g_failure_type G_S_test(...);
+  };
+
+  template<typename G_MemPtr, typename G_Arg>
+    struct g_result_of_memobj_deref
+    : private g_result_of_memobj_deref_impl
+    {
+      using type = decltype(G_S_test<G_MemPtr, G_Arg>(0));
+    };
+
+  template<typename G_MemPtr, typename G_Arg>
+    struct g_result_of_memobj;
+
+  template<typename G_Res, typename G_Class, typename G_Arg>
+    struct g_result_of_memobj<G_Res G_Class::*, G_Arg>
+    {
+      using G_Argval = g_remove_cvref_t<G_Arg>;
+      using G_MemPtr = G_Res G_Class::*;
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3655. The INVOKE operation and union types
+      using type = typename std::conditional_t<or_<std::is_same<G_Argval, G_Class>,
+        std::is_base_of<G_Class, G_Argval>>::value,
+        g_result_of_memobj_ref<G_MemPtr, G_Arg>,
+        g_result_of_memobj_deref<G_MemPtr, G_Arg>
+      >::type;
+    };
+
+  template<typename G_MemPtr, typename G_Arg, typename... G_Args>
+    struct g_result_of_memfun;
+
+  template<typename G_Res, typename G_Class, typename G_Arg, typename... G_Args>
+    struct g_result_of_memfun<G_Res G_Class::*, G_Arg, G_Args...>
+    {
+      using G_Argval = typename std::remove_reference<G_Arg>::type;
+      using G_MemPtr = G_Res G_Class::*;
+      using type = typename std::conditional_t<std::is_base_of<G_Class, G_Argval>::value,
+        g_result_of_memfun_ref<G_MemPtr, G_Arg, G_Args...>,
+        g_result_of_memfun_deref<G_MemPtr, G_Arg, G_Args...>
+      >::type;
+    };
+
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2219.  INVOKE-ing a pointer to member with a reference_wrapper
+  //        as the object expression
+
+  // Used by result_of, invoke etc. to unwrap a reference_wrapper.
+  template<typename G_Tp, typename G_Up = g_remove_cvref_t<G_Tp>>
+    struct g_inv_unwrap
+    {
+      using type = G_Tp;
+    };
+
+  template<typename G_Tp, typename G_Up>
+    struct g_inv_unwrap<G_Tp, std::reference_wrapper<G_Up>>
+    {
+      using type = G_Up&;
+    };
+
+  template<bool, bool, typename G_Functor, typename... G_ArgTypes>
+    struct g_result_of_impl
+    {
+      using type = g_failure_type;
+    };
+
+  template<typename G_MemPtr, typename G_Arg>
+    struct g_result_of_impl<true, false, G_MemPtr, G_Arg>
+    : public g_result_of_memobj<std::decay_t<G_MemPtr>,
+				typename g_inv_unwrap<G_Arg>::type>
+    { };
+
+  template<typename G_MemPtr, typename G_Arg, typename... G_Args>
+    struct g_result_of_impl<false, true, G_MemPtr, G_Arg, G_Args...>
+    : public g_result_of_memfun<std::decay_t<G_MemPtr>,
+				typename g_inv_unwrap<G_Arg>::type, G_Args...>
+    { };
+
+  // [func.require] paragraph 1 bullet 5:
+  struct g_result_of_other_impl
+  {
+    template<typename G_Fn, typename... G_Args>
+      static g_result_of_success<decltype(
+      std::declval<G_Fn>()(std::declval<G_Args>()...)
+      ), g_invoke_other> G_S_test(int);
+
+    template<typename...>
+      static g_failure_type G_S_test(...);
+  };
+
+  template<typename G_Functor, typename... G_ArgTypes>
+    struct g_result_of_impl<false, false, G_Functor, G_ArgTypes...>
+    : private g_result_of_other_impl
+    {
+      using type = decltype(G_S_test<G_Functor, G_ArgTypes...>(0));
+    };
+
+  // __invoke_result (std::invoke_result for C++11)
+  template<typename G_Functor, typename... G_ArgTypes>
+    struct g_invoke_result
+    : public g_result_of_impl<
+        std::is_member_object_pointer<
+          typename std::remove_reference<G_Functor>::type
+        >::value,
+        std::is_member_function_pointer<
+          typename std::remove_reference<G_Functor>::type
+        >::value,
+	G_Functor, G_ArgTypes...
+      >::type
+    { };
+
+  // __invoke_result_t (std::invoke_result_t for C++11)
+  template<typename G_Fn, typename... G_Args>
+    using g_invoke_result_t = typename g_invoke_result<G_Fn, G_Args...>::type;
+  /// @endcond
+
+  // __is_invocable (std::is_invocable for C++11)
+
+  // The primary template is used for invalid INVOKE expressions.
+  template<typename G_Result, typename G_Ret,
+	   bool = std::is_void<G_Ret>::value, typename = void>
+    struct g_is_invocable_impl
+    : std::false_type
+    {
+      using g_nothrow_conv = std::false_type; // For is_nothrow_invocable_r
+    };
+
+  // Used for valid INVOKE and INVOKE<void> expressions.
+  template<typename G_Result, typename G_Ret>
+    struct g_is_invocable_impl<G_Result, G_Ret,
+			       /* is_void<_Ret> = */ true,
+			       void_t<typename G_Result::type>>
+    : std::true_type
+    {
+      using g_nothrow_conv = std::true_type; // For is_nothrow_invocable_r
+    };
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
+  // Used for INVOKE<R> expressions to check the implicit conversion to R.
+  template<typename G_Result, typename G_Ret>
+    struct g_is_invocable_impl<G_Result, G_Ret,
+			       /* is_void<_Ret> = */ false,
+			       void_t<typename G_Result::type>>
+    {
+    private:
+      // The type of the INVOKE expression.
+      using G_Res_t = typename G_Result::type;
+
+      // Unlike declval, this doesn't add_rvalue_reference, so it respects
+      // guaranteed copy elision.
+      static G_Res_t G_S_get() noexcept;
+
+      // Used to check if _Res_t can implicitly convert to _Tp.
+      template<typename G_Tp>
+	static void G_S_conv(g_type_identity_t<G_Tp>) noexcept;
+
+      // This overload is viable if INVOKE(f, args...) can convert to _Tp.
+      template<typename G_Tp,
+	       bool G_Nothrow = noexcept(G_S_conv<G_Tp>(G_S_get())),
+	       typename = decltype(G_S_conv<G_Tp>(G_S_get())),
+#if gcc_backport_has_builtin(__reference_converts_from_temporary)
+	       bool G_Dangle = __reference_converts_from_temporary(G_Tp, G_Res_t)
+#else
+	       bool G_Dangle = false
+#endif
+	      >
+	static detail::to_bool_trait<G_Nothrow && !G_Dangle>
+	G_S_test(int);
+
+      template<typename G_Tp, bool = false>
+	static std::false_type
+	G_S_test(...);
+
+    public:
+      // For is_invocable_r
+      using type = decltype(G_S_test<G_Ret, /* Nothrow = */ true>(1));
+
+      // For is_nothrow_invocable_r
+      using g_nothrow_conv = decltype(G_S_test<G_Ret>(1));
+    };
+#pragma GCC diagnostic pop
+
+  template<typename G_Fn, typename... G_ArgTypes>
+    struct g_is_invocable
+    : g_is_invocable_impl<g_invoke_result<G_Fn, G_ArgTypes...>, void>::type
+    { };
+
+  template<typename G_Fn, typename G_Tp, typename... G_Args>
+    constexpr bool g_call_is_nt(g_invoke_memfun_ref)
+    {
+      using G_Up = typename g_inv_unwrap<G_Tp>::type;
+      return noexcept((std::declval<G_Up>().*std::declval<G_Fn>())(
+	    std::declval<G_Args>()...));
+    }
+
+  template<typename G_Fn, typename G_Tp, typename... G_Args>
+    constexpr bool g_call_is_nt(g_invoke_memfun_deref)
+    {
+      return noexcept(((*std::declval<G_Tp>()).*std::declval<G_Fn>())(
+	    std::declval<G_Args>()...));
+    }
+
+  template<typename G_Fn, typename G_Tp>
+    constexpr bool g_call_is_nt(g_invoke_memobj_ref)
+    {
+      using G_Up = typename g_inv_unwrap<G_Tp>::type;
+      return noexcept(std::declval<G_Up>().*std::declval<G_Fn>());
+    }
+
+  template<typename G_Fn, typename G_Tp>
+    constexpr bool g_call_is_nt(g_invoke_memobj_deref)
+    {
+      return noexcept((*std::declval<G_Tp>()).*std::declval<G_Fn>());
+    }
+
+  template<typename G_Fn, typename... G_Args>
+    constexpr bool g_call_is_nt(g_invoke_other)
+    {
+      return noexcept(std::declval<G_Fn>()(std::declval<G_Args>()...));
+    }
+
+  template<typename G_Result, typename G_Fn, typename... G_Args>
+    struct g_call_is_nothrow
+    : detail::to_bool_trait<
+	g_call_is_nt<G_Fn, G_Args...>(typename G_Result::g_invoke_type{})
+      >
+    { };
+
+  template<typename G_Fn, typename... G_Args>
+    using g_call_is_nothrow_
+      = g_call_is_nothrow<g_invoke_result<G_Fn, G_Args...>, G_Fn, G_Args...>;
+
+  // __is_nothrow_invocable (std::is_nothrow_invocable for C++11)
+  template<typename G_Fn, typename... G_Args>
+    struct g_is_nothrow_invocable
+    : and_<g_is_invocable<G_Fn, G_Args...>,
+             g_call_is_nothrow_<G_Fn, G_Args...>>::type
+    { };
+
+  // std::is_unbounded_array backport
+  template<typename G_Tp>
+    struct is_unbounded_array : std::false_type {};
+
+  template<typename G_Tp>
+    struct is_unbounded_array<G_Tp[]> : std::true_type {};
+
+  // true_type if G_Tp has cv-quals.
+  template<typename G_Tp>
+    using is_cv_qualified = not_<std::is_same<G_Tp, std::remove_cv_t<G_Tp>>>;
+
+  // Helpers for relational operators.  Trick borrowed from <optional>.
+  namespace detail {
+    template<typename... G_Tp>
+      using relop_return_t = std::enable_if_t<
+	and_<std::is_convertible<G_Tp, bool>...>::value,
+	bool
+	>;
+  }
+
+  // 'bool' if G_Tp has equality operator, otherwise SFINAE fail.
+  template<typename G_Tp, typename G_Up = G_Tp>
+    using eql_return_t = detail::relop_return_t<
+      decltype(std::declval<const G_Tp&>() == std::declval<const G_Up&>())
+      >;
+
+
+  template<typename G_Tp, typename G_Wp>
+    using g_converts_from_any_cvref = or_<
+	std::is_constructible<G_Tp, G_Wp&>,       std::is_convertible<G_Wp&, G_Tp>,
+	std::is_constructible<G_Tp, G_Wp>,        std::is_convertible<G_Wp, G_Tp>,
+	std::is_constructible<G_Tp, const G_Wp&>, std::is_convertible<const G_Wp&, G_Tp>,
+	std::is_constructible<G_Tp, const G_Wp>,  std::is_convertible<const G_Wp, G_Tp>
+      >;
+
+  template<typename... G_Cond>
+    using G_Requires = std::enable_if_t<and_<G_Cond...>::value, bool>;
+
+
+  template<typename G_Tp>
+    struct g_is_array_known_bounds
+    : public std::false_type
+    { };
+
+  template<typename G_Tp, std::size_t G_Size>
+    struct g_is_array_known_bounds<G_Tp[G_Size]>
+    : public std::true_type
+    { };
+
+  template<typename G_Tp>
+    struct g_is_array_unknown_bounds
+    : public std::false_type
+    { };
+
+  template<typename G_Tp>
+    struct g_is_array_unknown_bounds<G_Tp[]>
+    : public std::true_type
+    { };
+
+  // An object type which is not an unbounded array.
+  // It might still be an incomplete type, but if this is false_type
+  // then we can be certain it's not a complete object type.
+  template<typename G_Tp>
+    using g_maybe_complete_object_type
+      = and_<std::is_object<G_Tp>, not_<g_is_array_unknown_bounds<G_Tp>>>;
+
+  // Helper functions that return false_type for incomplete classes,
+  // incomplete unions and arrays of known bound from those.
+
+  // More specialized overload for complete object types (returning true_type).
+  template<typename G_Tp,
+	   typename = std::enable_if_t<g_maybe_complete_object_type<G_Tp>::value>,
+	   std::size_t = sizeof(G_Tp)>
+    constexpr std::true_type
+    g_is_complete_or_unbounded(g_type_identity<G_Tp>)
+    { return {}; };
+
+  // Less specialized overload for reference and unknown-bound array types
+  // (returning true_type), and incomplete types (returning false_type).
+  template<typename G_TypeIdentity,
+	   typename G_NestedType = typename G_TypeIdentity::type>
+    constexpr typename not_<g_maybe_complete_object_type<G_NestedType>>::type
+    g_is_complete_or_unbounded(G_TypeIdentity)
+    { return {}; }
+
+
+#if gcc_backport_has_builtin(__reference_converts_from_temporary)
+  /// True if _Tp is a reference type, a _Up value can be bound to _Tp in
+  /// copy-initialization, and a temporary object would be bound to
+  /// the reference, false otherwise.
+  /// @since C++23
+  template<typename _Tp, typename _Up>
+    struct reference_converts_from_temporary
+    : public detail::to_bool_trait<__reference_converts_from_temporary(_Tp, _Up)>
+    {
+      static_assert(g_is_complete_or_unbounded(g_type_identity<_Tp>{})
+		    && g_is_complete_or_unbounded(g_type_identity<_Up>{}),
+	"template argument must be a complete class or an unbounded array");
+    };
+#else
+  // Hopefully, this trait is only ever used to enable developer diagnostics,
+  // and doesn't impact correctness.
+  template<typename _Tp, typename _Up>
+    struct reference_converts_from_temporary : std::false_type {};
+#endif
+
+#if gcc_backport_has_builtin(__reference_converts_from_temporary)
+  /// True if _Tp is a reference type, a _Up value can be bound to _Tp in
+  /// direct-initialization, and a temporary object would be bound to
+  /// the reference, false otherwise.
+  /// @since C++23
+  template<typename G_Tp, typename G_Up>
+    struct reference_constructs_from_temporary
+    : public detail::to_bool_trait<__reference_constructs_from_temporary(G_Tp, G_Up)>
+    {
+      static_assert(g_is_complete_or_unbounded(g_type_identity<G_Tp>{})
+		    && g_is_complete_or_unbounded(g_type_identity<G_Up>{}),
+	"template argument must be a complete class or an unbounded array");
+    };
+#else
+  // Hopefully, this trait is only ever used to enable developer diagnostics,
+  // and doesn't impact correctness.
+  template<typename _Tp, typename _Up>
+    struct reference_constructs_from_temporary : std::false_type {};
+#endif
+}
+
+#endif // GCC_BACKPORT_BITS_MORE_TYPE_TRAITS_H
diff --git a/gcc/stdbackport/gbits/optional_ref.h b/gcc/stdbackport/gbits/optional_ref.h
new file mode 100644
index 000000000000..b1f69d73a020
--- /dev/null
+++ b/gcc/stdbackport/gbits/optional_ref.h
@@ -0,0 +1,550 @@
+// optional<T&> -*- C++ -*-
+
+// Copyright (C) 2013-2026 Free Software Foundation, Inc.
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/optional_ref.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{optional}
+ */
+
+#ifndef GCC_BACKPORT_GLIBCXX_OPTIONAL_REF
+#define GCC_BACKPORT_GLIBCXX_OPTIONAL_REF 1
+
+#include <type_traits>
+#include <utility>
+#include "inplace_tags.h"
+#include "more_type_traits.h"
+
+namespace gcc
+{
+
+   /**
+   *  @addtogroup utilities
+   *  @{
+   */
+
+  template<typename G_Tp>
+    class optional;
+
+  /// Tag type to disengage optional objects.
+  struct nullopt_t
+  {
+    // Do not user-declare default constructor at all for
+    // optional_value = {} syntax to work.
+    // nullopt_t() = delete;
+
+    // Used for constructing nullopt.
+    enum class G_Construct { G_Token };
+
+    // Must be constexpr for nullopt_t to be literal.
+    explicit constexpr nullopt_t(G_Construct) noexcept { }
+  };
+
+  /// Tag to disengage optional objects.
+  static constexpr nullopt_t nullopt { nullopt_t::G_Construct::G_Token };
+
+  template<typename G_Fn> struct G_Optional_func { G_Fn& G_M_f; };
+
+  template<typename G_Tp>
+    static constexpr bool g_is_valid_contained_type_for_optional =
+      (
+	std::is_lvalue_reference<G_Tp>::value ||
+	(std::is_object<G_Tp>::value && std::is_destructible<G_Tp>::value && !std::is_array<G_Tp>::value)
+      )
+      && !std::is_same<std::remove_cv_t<std::remove_reference_t<G_Tp>>, nullopt_t>::value
+      && !std::is_same<std::remove_cv_t<std::remove_reference_t<G_Tp>>, in_place_t>::value;
+
+  template<typename G_Tp>
+    class optional<G_Tp&>;
+
+  template<typename G_Tp>
+  struct g_is_optional_ref : std::false_type {};
+
+  template<typename G_Tp>
+  struct g_is_optional_ref<optional<G_Tp&>> : std::true_type {};
+
+  template<typename G_Tp>
+    struct g_optional_ref_base
+    {};
+
+  template<typename G_Tp>
+    class optional<G_Tp&> : public g_optional_ref_base<G_Tp>
+    {
+      static_assert(g_is_valid_contained_type_for_optional<G_Tp&>,
+		    "Given type not valid for an optional");
+
+    public:
+      using value_type = G_Tp;
+
+      constexpr static optional
+      G_S_from_ptr(G_Tp* g_ptr)
+      {
+	optional g_res;
+	g_res.G_M_val = g_ptr;
+	return g_res;
+      }
+
+      // Constructors.
+      constexpr optional() noexcept = default;
+      constexpr optional(nullopt_t) noexcept : optional() {}
+      constexpr optional(const optional&) noexcept = default;
+
+      template<typename G_Arg,
+	       G_Requires<
+		 std::is_constructible<G_Tp&, G_Arg>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Arg>>
+		 > = false>
+	explicit constexpr
+	optional(in_place_t, G_Arg&& g_arg)
+	{
+	  g_convert_ref_init_val(std::forward<G_Arg>(g_arg));
+	}
+
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, optional>>,
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, in_place_t>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up>>,
+
+		 // Explicit:
+		 not_<std::is_convertible<G_Up, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(G_Up&& g_u)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up>::value)
+	{
+	  g_convert_ref_init_val(std::forward<G_Up>(g_u));
+	}
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, optional>>,
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, in_place_t>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up>>,
+
+		 // !Explicit:
+		 std::is_convertible<G_Up, G_Tp&>
+		 > = false>
+	constexpr
+	optional(G_Up&& g_u)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up>::value)
+	{
+	  g_convert_ref_init_val(std::forward<G_Up>(g_u));
+	}
+
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, optional>>,
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, in_place_t>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 reference_constructs_from_temporary<G_Tp&, G_Up>,
+
+		 // Explicit:
+		 not_<std::is_convertible<G_Up, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(G_Up&& g_u) = delete;
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, optional>>,
+		 not_<std::is_same<g_remove_cvref_t<G_Up>, in_place_t>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 reference_constructs_from_temporary<G_Tp&, G_Up>,
+
+		 // !Explicit:
+		 std::is_convertible<G_Up, G_Tp&>
+		 > = false>
+	constexpr
+	optional(G_Up&& g_u) = delete;
+
+      // optional<U> &
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up&>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up&>>,
+
+		 // Explicit:
+		 not_<std::is_convertible<G_Up&, G_Tp&>>
+		 > = false>
+        explicit
+	constexpr
+	optional(optional<G_Up>& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up&>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(g_rhs.G_M_fwd());
+	}
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up&>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up&>>,
+
+		 // !Explicit:
+		 std::is_convertible<G_Up&, G_Tp&>
+		 > = false>
+	constexpr
+	optional(optional<G_Up>& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up&>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(g_rhs.G_M_fwd());
+	}
+
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up&>,
+		 reference_constructs_from_temporary<G_Tp&, G_Up&>,
+
+		 // Explicit:
+		 not_<std::is_convertible<G_Up&, G_Tp&>>
+		 > = false>
+        explicit
+	constexpr
+	optional(optional<G_Up>& g_rhs) = delete;
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up&>,
+		 reference_constructs_from_temporary<G_Tp&, G_Up&>,
+
+		 // !Explicit:
+		 std::is_convertible<G_Up&, G_Tp&>
+		 > = false>
+	constexpr
+	optional(optional<G_Up>& g_rhs) = delete;
+
+      // const optional<U>&
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up&>,
+		 not_<reference_constructs_from_temporary<G_Tp&, const G_Up&>>,
+
+		 // Explicit:
+		 not_<std::is_convertible<const G_Up&, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(const optional<G_Up>& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up&>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(g_rhs.G_M_fwd());
+	}
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up&>,
+		 not_<reference_constructs_from_temporary<G_Tp&, const G_Up&>>,
+
+		 // !Explicit:
+		 std::is_convertible<const G_Up&, G_Tp&>
+		 > = false>
+	constexpr
+	optional(const optional<G_Up>& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up&>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(g_rhs.G_M_fwd());
+	}
+
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up&>,
+		 reference_constructs_from_temporary<G_Tp&, const G_Up&>,
+
+		 // Explicit:
+		 not_<std::is_convertible<const G_Up&, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(const optional<G_Up>& g_rhs) = delete;
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up&>,
+		 reference_constructs_from_temporary<G_Tp&, const G_Up&>,
+
+		 // !Explicit:
+		 std::is_convertible<const G_Up&, G_Tp&>
+		 > = false>
+	constexpr
+	optional(const optional<G_Up>& g_rhs) = delete;
+
+      // optional<U>&&
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up>>,
+
+		 // Explicit:
+		 not_<std::is_convertible<G_Up, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(optional<G_Up>&& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(std::move(g_rhs).G_M_fwd());
+	}
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up>>,
+
+		 // !Explicit:
+		 std::is_convertible<G_Up, G_Tp&>
+		 > = false>
+	constexpr
+	optional(optional<G_Up>&& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(std::move(g_rhs).G_M_fwd());
+	}
+
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 reference_constructs_from_temporary<G_Tp&, G_Up>,
+
+		 // Explicit:
+		 not_<std::is_convertible<G_Up, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(optional<G_Up>&& g_rhs) = delete;
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, G_Up>,
+		 reference_constructs_from_temporary<G_Tp&, G_Up>,
+
+		 // !Explicit:
+		 std::is_convertible<G_Up, G_Tp&>
+		 > = false>
+	constexpr
+	optional(optional<G_Up>&& g_rhs) = delete;
+
+      // const optional<U>&&
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up>>,
+
+		 // Explicit:
+		 not_<std::is_convertible<const G_Up, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(const optional<G_Up>&& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, const G_Up>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(std::move(g_rhs).G_M_fwd());
+	}
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up>>,
+
+		 // !Explicit:
+		 std::is_convertible<const G_Up, G_Tp&>
+		 > = false>
+	constexpr
+	optional(const optional<G_Up>&& g_rhs)
+	noexcept(std::is_nothrow_constructible<G_Tp&, const G_Up>::value)
+	{
+	  if (g_rhs)
+	    g_convert_ref_init_val(std::move(g_rhs).G_M_fwd());
+	}
+
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up>,
+		 reference_constructs_from_temporary<G_Tp&, const G_Up>,
+
+		 // Explicit:
+		 not_<std::is_convertible<const G_Up, G_Tp&>>
+		 > = false>
+	explicit
+	constexpr
+	optional(const optional<G_Up>&& g_rhs) = delete;
+      template<typename G_Up,
+	       G_Requires<
+		 not_<std::is_same<std::remove_cv_t<G_Tp>, optional<G_Up>>>,
+		 not_<std::is_same<G_Tp&, G_Up>>,
+		 std::is_constructible<G_Tp&, const G_Up>,
+		 reference_constructs_from_temporary<G_Tp&, const G_Up>,
+
+		 // !Explicit:
+		 std::is_convertible<const G_Up, G_Tp&>
+		 > = false>
+	constexpr
+	optional(const optional<G_Up>&& g_rhs) = delete;
+
+      GCC_BACKPORT20_CONSTEXPR ~optional() = default;
+
+      // Assignment.
+      constexpr optional& operator=(nullopt_t) noexcept
+      {
+	G_M_val = nullptr;
+	return *this;
+      }
+
+      constexpr optional& operator=(const optional&) noexcept = default;
+
+      template<typename G_Up,
+	       G_Requires<
+		 std::is_constructible<G_Tp&, G_Up>,
+		 not_<reference_constructs_from_temporary<G_Tp&, G_Up>>
+		 > = false>
+	constexpr G_Tp&
+	emplace(G_Up&& g_u)
+	noexcept(std::is_nothrow_constructible<G_Tp&, G_Up>::value)
+	{
+	  g_convert_ref_init_val(std::forward<G_Up>(g_u));
+	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	  // 4300. Missing Returns: element in optional<T&>::emplace
+	  return *G_M_val;
+	}
+
+      // Swap.
+      constexpr void swap(optional& g_rhs) noexcept
+      { std::swap(G_M_val, g_rhs.G_M_val); }
+
+      // Observers.
+      constexpr G_Tp* operator->() const noexcept
+      {
+	__glibcxx_assert(G_M_val); // hardened precondition
+	return G_M_val;
+      }
+
+      constexpr G_Tp& operator*() const noexcept
+      {
+	__glibcxx_assert(G_M_val); // hardened precondition
+	return *G_M_val;
+      }
+
+      constexpr explicit operator bool() const noexcept
+      {
+	return G_M_val;
+      }
+
+      constexpr bool has_value() const noexcept
+      {
+	return G_M_val;
+      }
+
+      constexpr G_Tp& value() const;
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 4304. std::optional<NonReturnable&> is ill-formed due to value_or
+      template<typename G_Up = std::remove_cv_t<G_Tp>,
+	       typename G_Tp_ = G_Tp,
+	       G_Requires<
+		 std::is_object<G_Tp_>,
+		 not_<std::is_array<G_Tp_>>
+		 > = false>
+	constexpr std::decay_t<G_Tp>
+	value_or(G_Up&& g_u) const;
+
+      // Monadic operations.
+      template<typename G_Fn>
+	constexpr auto
+	and_then(G_Fn&& g_f) const;
+
+      template<typename G_Fn>
+	constexpr
+	optional<std::remove_cv_t<g_invoke_result_t<G_Fn, G_Tp&>>>
+	transform(G_Fn&& g_f) const;
+
+      template<typename G_Fn,
+	       G_Requires<g_is_invocable<G_Fn>> = false>
+	constexpr
+	optional
+	or_else(G_Fn&& g_f) const;
+
+      // Modifiers.
+      constexpr void reset() noexcept
+      {
+	G_M_val = nullptr;
+      }
+
+    private:
+      G_Tp *G_M_val = nullptr;
+
+      [[__gnu__::__always_inline__]]
+      constexpr G_Tp&
+      G_M_fwd() const noexcept
+      { return *G_M_val; }
+
+      template<typename G_Up> friend class optional;
+
+      template<typename G_Up>
+	constexpr
+	void
+	g_convert_ref_init_val(G_Up&& g_u)
+	noexcept
+	{
+	  G_Tp& g_r(std::forward<G_Up>(g_u));
+	  G_M_val = std::addressof(g_r);
+	}
+
+      template<typename G_Fn, typename G_Value>
+	explicit constexpr
+	optional(G_Optional_func<G_Fn> g_f, G_Value&& g_v);
+    };
+} // namespace gcc
+
+#endif // GCC_BACKPORT_GLIBCXX_OPTIONAL_REF
diff --git a/gcc/stdbackport/gbits/stl_construct.h b/gcc/stdbackport/gbits/stl_construct.h
new file mode 100644
index 000000000000..a8a26a0dcf3a
--- /dev/null
+++ b/gcc/stdbackport/gbits/stl_construct.h
@@ -0,0 +1,162 @@
+// nonstandard construct and destroy functions -*- C++ -*-
+
+// Copyright (C) 2001-2026 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/*
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ */
+
+/** @file bits/stl_construct.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{memory}
+ */
+
+#ifndef GCC_BACKPORT_STL_CONSTRUCT_H
+#define GCC_BACKPORT_STL_CONSTRUCT_H 1
+
+#include <memory>
+#include <utility>
+#include "more_type_traits.h"
+
+/* This file provides the C++17 functions std::destroy_at, std::destroy, and
+ * std::destroy_n, and the C++20 function std::construct_at.
+ * It also provides std::_Construct, std::_Destroy,and std::_Destroy_n functions
+ * which are defined in all standard modes and so can be used in C++98-14 code.
+ * The _Destroy functions will dispatch to destroy_at during constant
+ * evaluation, because calls to that function are intercepted by the compiler
+ * to allow use in constant expressions.
+ */
+
+namespace gcc
+{
+
+  /**
+   * Constructs an object in existing memory by invoking an allocated
+   * object's constructor with an initializer.
+   */
+  template<typename G_Tp, typename... G_Args>
+    GCC_BACKPORT20_CONSTEXPR
+    inline void
+    G_Construct(G_Tp* g_p, G_Args&&... g_args)
+    {
+#if __cpp_constexpr_dynamic_alloc // >= C++20
+      if (std::is_constant_evaluated())
+	{
+	  // Allow std::_Construct to be used in constant expressions.
+	  std::construct_at(g_p, std::forward<G_Args>(g_args)...);
+	  return;
+	}
+#endif
+      ::new(static_cast<void*>(g_p)) G_Tp(std::forward<G_Args>(g_args)...);
+    }
+
+  /**
+   * Destroy the object pointed to by a pointer type.
+   */
+  template<typename G_Tp>
+    constexpr inline std::enable_if_t<!std::is_array<G_Tp>::value>
+    G_Destroy(G_Tp* g_pointer)
+    {
+      g_pointer->~G_Tp();
+    }
+
+  template <typename G_Tp>
+  inline std::enable_if_t<std::is_array<G_Tp>::value>
+    G_Destroy(G_Tp* __location)
+    {
+      for (auto& __x : *__location)
+	gcc::G_Destroy(std::addressof(__x));
+    }
+
+#if __cplusplus < 202002L
+  namespace detail {
+    template<typename G_Up, typename... G_Args>
+      static decltype (::new((void*)0) G_Up(std::declval<G_Args>()...),
+		       std::true_type {})
+      placement_new_test (int);
+
+    template<typename G_Up, typename... G_Args>
+      static std::false_type
+      placement_new_test (...);
+  } // namespace detail
+
+  template<typename G_Tp, typename... G_Args>
+    using can_placement_new
+      = decltype(detail::placement_new_test<G_Tp, G_Args...>(0));
+
+  template<typename G_Tp, typename... G_Args>
+  using can_use_construct_at = and_<can_placement_new<G_Tp, G_Args...>,
+				    not_<is_unbounded_array<G_Tp>>>;
+
+  template<typename G_Tp, typename... G_Args>
+    constexpr std::enable_if_t<and_<can_use_construct_at<G_Tp, G_Args...>,
+				    std::is_array<G_Tp>>::value,
+			       G_Tp*>
+  construct_at (G_Tp* g_location, G_Args&&...)
+  {
+    void* g_loc = g_location;
+    static_assert(sizeof...(G_Args) == 0, "std::construct_at for array "
+		  "types must not use any arguments to initialize the "
+		  "array");
+    return ::new(g_loc) G_Tp[1]();
+  }
+  template<typename G_Tp, typename... G_Args>
+    constexpr std::enable_if_t<and_<can_use_construct_at<G_Tp, G_Args...>,
+				    not_<std::is_array<G_Tp>>>::value,
+			       G_Tp*>
+  construct_at (G_Tp* g_location, G_Args&&... g_args)
+  {
+    void* g_loc = g_location;
+    return ::new(g_loc) G_Tp(std::forward<G_Args>(g_args)...);
+  }
+#else // C++ >= 20
+  // Use standard instead of our own implementation, to permit constexpr use.
+  // Useful for running testsuites against expected.
+  using std::construct_at;
+#endif
+
+} // namespace gcc
+
+#endif /* GCC_BACKPORT_STL_CONSTRUCT_H */
diff --git a/gcc/stdbackport/optional b/gcc/stdbackport/optional
new file mode 100644
index 000000000000..c899e6ea65f8
--- /dev/null
+++ b/gcc/stdbackport/optional
@@ -0,0 +1,1786 @@
+// <optional> -*- C++ -*-
+
+// Copyright (C) 2013-2026 Free Software Foundation, Inc.
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/optional
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef GCC_BACKPORT_GLIBCXX_OPTIONAL
+#define GCC_BACKPORT_GLIBCXX_OPTIONAL 1
+
+#define WANT_FUNCTIONAL
+#include "gbits/check_system_h.h"
+
+#include <type_traits>
+#include <initializer_list>
+
+#include "gbits/assert.h"
+#include "gbits/enable_special_members.h"
+#include "gbits/functional_hash.h"
+#include "gbits/exception_defines.h"
+#include "gbits/invoke.h"
+#include "gbits/more_type_traits.h"
+#include "gbits/optional_ref.h"  // nullopt_t, optional<_Tp&>
+#include "gbits/stl_construct.h" // _Construct
+
+#ifdef GCC_BACKPORT_WANT_EXCEPTIONS
+# include <exception>
+#endif
+
+#include "optionalfwd"
+
+namespace gcc
+{
+
+  /**
+   *  @addtogroup utilities
+   *  @{
+   */
+
+#ifdef GCC_BACKPORT_WANT_EXCEPTIONS
+  /**
+   *  @brief Exception class thrown when a disengaged optional object is
+   *  dereferenced.
+   *  @ingroup exceptions
+   */
+  class bad_optional_access : public std::exception
+  {
+  public:
+    bad_optional_access() = default;
+    virtual ~bad_optional_access() = default;
+
+#if __cpp_lib_constexpr_exceptions >= 202502L
+    constexpr
+#endif
+    const char* what() const noexcept override
+    { return "bad optional access"; }
+  };
+#endif
+
+  // XXX Does not belong here.
+  [[__noreturn__]]
+#if __cpp_lib_constexpr_exceptions >= 202502L
+  constexpr
+#else
+  inline
+#endif
+  void
+  g_throw_bad_optional_access()
+  { g_throw_or_abort(bad_optional_access()); }
+
+  // This class template manages construction/destruction of
+  // the contained value for a std::optional.
+  template <typename G_Tp>
+    struct G_Optional_payload_base
+    {
+      using G_Stored_type = std::remove_const_t<G_Tp>;
+
+      G_Optional_payload_base() = default;
+      ~G_Optional_payload_base() = default;
+
+      template<typename... G_Args>
+	constexpr
+	G_Optional_payload_base(in_place_t g_tag, G_Args&&... g_args)
+	: G_M_payload(g_tag, std::forward<G_Args>(g_args)...),
+	  G_M_engaged(true)
+	{ }
+
+      template<typename G_Up, typename... G_Args>
+	constexpr
+	G_Optional_payload_base(std::initializer_list<G_Up> g_il,
+			       G_Args&&... g_args)
+	: G_M_payload(g_il, std::forward<G_Args>(g_args)...),
+	  G_M_engaged(true)
+	{ }
+
+      // Constructor used by _Optional_base copy constructor when the
+      // contained value is not trivially copy constructible.
+      constexpr
+      G_Optional_payload_base(bool /* __engaged */,
+			     const G_Optional_payload_base& g_other)
+      {
+	if (g_other.G_M_engaged)
+	  this->G_M_construct(g_other.G_M_get());
+      }
+
+      // Constructor used by _Optional_base move constructor when the
+      // contained value is not trivially move constructible.
+      constexpr
+      G_Optional_payload_base(bool /* __engaged */,
+			     G_Optional_payload_base&& g_other)
+      {
+	if (g_other.G_M_engaged)
+	  this->G_M_construct(std::move(g_other.G_M_get()));
+      }
+
+      // Copy constructor is only used to when the contained value is
+      // trivially copy constructible.
+      G_Optional_payload_base(const G_Optional_payload_base&) = default;
+
+      // Move constructor is only used to when the contained value is
+      // trivially copy constructible.
+      G_Optional_payload_base(G_Optional_payload_base&&) = default;
+
+      G_Optional_payload_base&
+      operator=(const G_Optional_payload_base&) = default;
+
+      G_Optional_payload_base&
+      operator=(G_Optional_payload_base&&) = default;
+
+      // used to perform non-trivial copy assignment.
+      constexpr void
+      G_M_copy_assign(const G_Optional_payload_base& g_other)
+      {
+	if (this->G_M_engaged && g_other.G_M_engaged)
+	  this->G_M_get() = g_other.G_M_get();
+	else
+	  {
+	    if (g_other.G_M_engaged)
+	      this->G_M_construct(g_other.G_M_get());
+	    else
+	      this->G_M_reset();
+	  }
+      }
+
+      // used to perform non-trivial move assignment.
+      constexpr void
+      G_M_move_assign(G_Optional_payload_base&& g_other)
+      noexcept(and_<std::is_nothrow_move_constructible<G_Tp>,
+		       std::is_nothrow_move_assignable<G_Tp>>::value)
+      {
+	if (this->G_M_engaged && g_other.G_M_engaged)
+	  this->G_M_get() = std::move(g_other.G_M_get());
+	else
+	  {
+	    if (g_other.G_M_engaged)
+	      this->G_M_construct(std::move(g_other.G_M_get()));
+	    else
+	      this->G_M_reset();
+	  }
+      }
+
+      struct G_Empty_byte { };
+
+      template<typename G_Up, bool = std::is_trivially_destructible<G_Up>::value>
+	union G_Storage
+	{
+	  constexpr G_Storage() noexcept : G_M_empty() { }
+
+	  template<typename... G_Args>
+	    constexpr
+	    G_Storage(in_place_t, G_Args&&... g_args)
+	    : G_M_value(std::forward<G_Args>(g_args)...)
+	    { }
+
+	  template<typename G_Vp, typename... G_Args>
+	    constexpr
+	    G_Storage(std::initializer_list<G_Vp> g_il, G_Args&&... g_args)
+	    : G_M_value(g_il, std::forward<G_Args>(g_args)...)
+	    { }
+
+	  template<typename G_Fn, typename G_Arg>
+	    constexpr
+	    G_Storage(G_Optional_func<G_Fn> g_f, G_Arg&& g_arg)
+	    : G_M_value(gcc::invoke(std::forward<G_Fn>(g_f.G_M_f),
+				     std::forward<G_Arg>(g_arg)))
+	    { }
+
+	  G_Empty_byte G_M_empty;
+	  G_Up G_M_value;
+	};
+
+      template<typename G_Up>
+	union G_Storage<G_Up, false>
+	{
+	  constexpr G_Storage() noexcept : G_M_empty() { }
+
+	  template<typename... G_Args>
+	    constexpr
+	    G_Storage(in_place_t, G_Args&&... g_args)
+	    : G_M_value(std::forward<G_Args>(g_args)...)
+	    { }
+
+	  template<typename G_Vp, typename... G_Args>
+	    constexpr
+	    G_Storage(std::initializer_list<G_Vp> g_il, G_Args&&... g_args)
+	    : G_M_value(g_il, std::forward<G_Args>(g_args)...)
+	    { }
+
+	  template<typename G_Fn, typename G_Arg>
+	    constexpr
+	    G_Storage(G_Optional_func<G_Fn> g_f, G_Arg&& g_arg)
+	    : G_M_value(gcc::invoke(std::forward<G_Fn>(g_f.G_M_f),
+				     std::forward<G_Arg>(g_arg)))
+	    { }
+
+	  // User-provided destructor is needed when _Up has non-trivial dtor.
+	  GCC_BACKPORT20_CONSTEXPR
+	  ~G_Storage() { }
+
+	  G_Storage(const G_Storage&) = default;
+	  G_Storage(G_Storage&&) = default;
+	  G_Storage& operator=(const G_Storage&) = default;
+	  G_Storage& operator=(G_Storage&&) = default;
+
+	  G_Empty_byte G_M_empty;
+	  G_Up G_M_value;
+	};
+
+      G_Storage<G_Stored_type> G_M_payload;
+
+      bool G_M_engaged = false;
+
+      template<typename... G_Args>
+	constexpr void
+	G_M_construct(G_Args&&... g_args)
+	noexcept(std::is_nothrow_constructible<G_Stored_type, G_Args...>::value)
+	{
+	  gcc::G_Construct(std::addressof(this->G_M_payload.G_M_value),
+			  std::forward<G_Args>(g_args)...);
+	  this->G_M_engaged = true;
+	}
+
+      constexpr void
+      G_M_destroy() noexcept
+      {
+	G_M_engaged = false;
+	G_M_payload.G_M_value.~G_Stored_type();
+#if defined(__clang__) && __cplusplus >= 202002L // full constexpr support
+	if (std::is_constant_evaluated())
+	  // Work around PR124910 for Clang.
+	  gcc::construct_at(std::addressof(G_M_payload.G_M_empty));
+#endif
+      }
+
+      template<typename G_Fn, typename G_Up>
+	constexpr void
+	G_M_apply(G_Optional_func<G_Fn> g_f, G_Up&& g_x)
+	{
+	  gcc::construct_at(std::addressof(this->G_M_payload),
+			    g_f, std::forward<G_Up>(g_x));
+	  G_M_engaged = true;
+	}
+
+      // The _M_get() operations have _M_engaged as a precondition.
+      // They exist to access the contained value with the appropriate
+      // const-qualification, because _M_payload has had the const removed.
+
+      constexpr G_Tp&
+      G_M_get() noexcept
+      { return this->G_M_payload.G_M_value; }
+
+      constexpr const G_Tp&
+      G_M_get() const noexcept
+      { return this->G_M_payload.G_M_value; }
+
+      // _M_reset is a 'safe' operation with no precondition.
+      constexpr void
+      G_M_reset() noexcept
+      {
+	if (this->G_M_engaged)
+	  G_M_destroy();
+	else // This seems redundant but improves codegen, see PR 112480.
+	  this->G_M_engaged = false;
+      }
+    };
+
+  // Class template that manages the payload for optionals.
+  template <typename G_Tp,
+	    bool /*_HasTrivialDestructor*/ =
+	      std::is_trivially_destructible<G_Tp>::value,
+	    bool /*_HasTrivialCopy */ =
+	      std::is_trivially_copy_assignable<G_Tp>::value
+	      && std::is_trivially_copy_constructible<G_Tp>::value,
+	    bool /*_HasTrivialMove */ =
+	      std::is_trivially_move_assignable<G_Tp>::value
+	      && std::is_trivially_move_constructible<G_Tp>::value>
+    struct G_Optional_payload;
+
+  // Payload for potentially-constexpr optionals (trivial copy/move/destroy).
+  template <typename G_Tp>
+    struct G_Optional_payload<G_Tp, true, true, true>
+    : G_Optional_payload_base<G_Tp>
+    {
+      using G_Optional_payload_base<G_Tp>::G_Optional_payload_base;
+
+      G_Optional_payload() = default;
+    };
+
+  // Payload for optionals with non-trivial copy construction/assignment.
+  template <typename G_Tp>
+    struct G_Optional_payload<G_Tp, true, false, true>
+    : G_Optional_payload_base<G_Tp>
+    {
+      using G_Optional_payload_base<G_Tp>::G_Optional_payload_base;
+
+      G_Optional_payload() = default;
+      ~G_Optional_payload() = default;
+      G_Optional_payload(const G_Optional_payload&) = default;
+      G_Optional_payload(G_Optional_payload&&) = default;
+      G_Optional_payload& operator=(G_Optional_payload&&) = default;
+
+      // Non-trivial copy assignment.
+      constexpr
+      G_Optional_payload&
+      operator=(const G_Optional_payload& g_other)
+      {
+	this->G_M_copy_assign(g_other);
+	return *this;
+      }
+    };
+
+  // Payload for optionals with non-trivial move construction/assignment.
+  template <typename G_Tp>
+    struct G_Optional_payload<G_Tp, true, true, false>
+    : G_Optional_payload_base<G_Tp>
+    {
+      using G_Optional_payload_base<G_Tp>::G_Optional_payload_base;
+
+      G_Optional_payload() = default;
+      ~G_Optional_payload() = default;
+      G_Optional_payload(const G_Optional_payload&) = default;
+      G_Optional_payload(G_Optional_payload&&) = default;
+      G_Optional_payload& operator=(const G_Optional_payload&) = default;
+
+      // Non-trivial move assignment.
+      constexpr
+      G_Optional_payload&
+      operator=(G_Optional_payload&& g_other)
+      noexcept(and_<std::is_nothrow_move_constructible<G_Tp>,
+		       std::is_nothrow_move_assignable<G_Tp>>::value)
+      {
+	this->G_M_move_assign(std::move(g_other));
+	return *this;
+      }
+    };
+
+  // Payload for optionals with non-trivial copy and move assignment.
+  template <typename G_Tp>
+    struct G_Optional_payload<G_Tp, true, false, false>
+    : G_Optional_payload_base<G_Tp>
+    {
+      using G_Optional_payload_base<G_Tp>::G_Optional_payload_base;
+
+      G_Optional_payload() = default;
+      ~G_Optional_payload() = default;
+      G_Optional_payload(const G_Optional_payload&) = default;
+      G_Optional_payload(G_Optional_payload&&) = default;
+
+      // Non-trivial copy assignment.
+      constexpr
+      G_Optional_payload&
+      operator=(const G_Optional_payload& g_other)
+      {
+	this->G_M_copy_assign(g_other);
+	return *this;
+      }
+
+      // Non-trivial move assignment.
+      constexpr
+      G_Optional_payload&
+      operator=(G_Optional_payload&& g_other)
+      noexcept(and_<std::is_nothrow_move_constructible<G_Tp>,
+		       std::is_nothrow_move_assignable<G_Tp>>::value)
+      {
+	this->G_M_move_assign(std::move(g_other));
+	return *this;
+      }
+    };
+
+  // Payload for optionals with non-trivial destructors.
+  template <typename G_Tp, bool G_Copy, bool G_Move>
+    struct G_Optional_payload<G_Tp, false, G_Copy, G_Move>
+    : G_Optional_payload<G_Tp, true, false, false>
+    {
+      // Base class implements all the constructors and assignment operators:
+      using G_Optional_payload<G_Tp, true, false, false>::G_Optional_payload;
+      G_Optional_payload() = default;
+      G_Optional_payload(const G_Optional_payload&) = default;
+      G_Optional_payload(G_Optional_payload&&) = default;
+      G_Optional_payload& operator=(const G_Optional_payload&) = default;
+      G_Optional_payload& operator=(G_Optional_payload&&) = default;
+
+      // Destructor needs to destroy the contained value:
+      GCC_BACKPORT20_CONSTEXPR ~G_Optional_payload() { this->G_M_reset(); }
+    };
+
+  /**
+    * @brief Class template that provides copy/move constructors of optional.
+    *
+    * Such a separate base class template is necessary in order to
+    * conditionally make copy/move constructors trivial.
+    *
+    * When the contained value is trivially copy/move constructible,
+    * the copy/move constructors of _Optional_base will invoke the
+    * trivial copy/move constructor of _Optional_payload. Otherwise,
+    * they will invoke _Optional_payload(bool, const _Optional_payload&)
+    * or _Optional_payload(bool, _Optional_payload&&) to initialize
+    * the contained value, if copying/moving an engaged optional.
+    *
+    * Whether the other special members are trivial is determined by the
+    * _Optional_payload<_Tp> specialization used for the _M_payload member.
+    *
+    * @see optional, _Enable_special_members
+    */
+  template<typename G_Tp,
+	   bool = std::is_trivially_copy_constructible<G_Tp>::value,
+	   bool = std::is_trivially_move_constructible<G_Tp>::value>
+    struct G_Optional_base
+    {
+      // Constructors for disengaged optionals.
+      constexpr G_Optional_base() = default;
+
+      // Constructors for engaged optionals.
+      template<typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp, G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t, G_Args&&... g_args)
+	: G_M_payload(in_place, std::forward<G_Args>(g_args)...)
+	{ }
+
+      template<typename G_Up, typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp,
+					      std::initializer_list<G_Up>&,
+					      G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t,
+			std::initializer_list<G_Up> g_il,
+			G_Args&&... g_args)
+	: G_M_payload(in_place, g_il, std::forward<G_Args>(g_args)...)
+	{ }
+
+      // Copy and move constructors.
+      constexpr
+      G_Optional_base(const G_Optional_base& g_other)
+      noexcept(std::is_nothrow_copy_constructible<G_Tp>::value)
+      : G_M_payload(g_other.G_M_payload.G_M_engaged, g_other.G_M_payload)
+      { }
+
+      constexpr
+      G_Optional_base(G_Optional_base&& g_other)
+      noexcept(std::is_nothrow_move_constructible<G_Tp>::value)
+      : G_M_payload(g_other.G_M_payload.G_M_engaged,
+		   std::move(g_other.G_M_payload))
+      { }
+
+      // Assignment operators.
+      G_Optional_base& operator=(const G_Optional_base&) = default;
+      G_Optional_base& operator=(G_Optional_base&&) = default;
+
+      G_Optional_payload<G_Tp> G_M_payload;
+
+    protected:
+      // For the primary template, we define these functions here.
+      using G_Stored_type = std::remove_const_t<G_Tp>;
+
+      // The _M_construct operation has !_M_engaged as a precondition
+      // while _M_destruct has _M_engaged as a precondition.
+      template<typename... G_Args>
+	constexpr void
+	G_M_construct(G_Args&&... g_args)
+	noexcept(std::is_nothrow_constructible<G_Stored_type, G_Args...>::value)
+	{
+	  G_M_payload.G_M_construct(std::forward<G_Args>(g_args)...);
+	}
+
+      constexpr void
+      G_M_destruct() noexcept
+      { G_M_payload.G_M_destroy(); }
+
+      // _M_reset is a 'safe' operation with no precondition.
+      constexpr void
+      G_M_reset() noexcept
+      { G_M_payload.G_M_reset(); }
+
+      constexpr bool G_M_is_engaged() const noexcept
+      { return G_M_payload.G_M_engaged; }
+
+      // The _M_get operations have _M_engaged as a precondition.
+      constexpr G_Tp&
+      G_M_get() noexcept
+      { return G_M_payload.G_M_get(); }
+
+      constexpr const G_Tp&
+      G_M_get() const noexcept
+      { return G_M_payload.G_M_get(); }
+    };
+
+  // If P0848R3 "Conditionally Trivial Special Member Functions" is not
+  // supported (as determined from the __cpp_concepts macro value), the
+  // _Optional_base primary template only has non-trivial copy and move
+  // constructors. Use partial specializations of _Optional_base<T, C, M>
+  // that have a trivial copy and/or move constructor.
+
+  // Common base class for _Optional_base<T> to avoid repeating these
+  // member functions in each partial specialization.
+  // Only used if P0848R3 "Conditionally Trivial Special Member Functions"
+  // is not supported, as indicated by the __cpp_concepts value.
+  template<typename G_Tp, typename G_Dp>
+    class G_Optional_base_impl
+    {
+    protected:
+      using G_Stored_type = std::remove_const_t<G_Tp>;
+
+      // The _M_construct operation has !_M_engaged as a precondition
+      // while _M_destruct has _M_engaged as a precondition.
+      template<typename... G_Args>
+	constexpr void
+	G_M_construct(G_Args&&... g_args)
+	noexcept(std::is_nothrow_constructible<G_Stored_type, G_Args...>::value)
+	{
+	  static_cast<G_Dp*>(this)->G_M_payload.G_M_construct(
+	    std::forward<G_Args>(g_args)...);
+	}
+
+      constexpr void
+      G_M_destruct() noexcept
+      { static_cast<G_Dp*>(this)->G_M_payload.G_M_destroy(); }
+
+      // _M_reset is a 'safe' operation with no precondition.
+      constexpr void
+      G_M_reset() noexcept
+      { static_cast<G_Dp*>(this)->G_M_payload.G_M_reset(); }
+
+      constexpr bool G_M_is_engaged() const noexcept
+      { return static_cast<const G_Dp*>(this)->G_M_payload.G_M_engaged; }
+
+      // The _M_get operations have _M_engaged as a precondition.
+      constexpr G_Tp&
+      G_M_get() noexcept
+      { return static_cast<G_Dp*>(this)->G_M_payload.G_M_get(); }
+
+      constexpr const G_Tp&
+      G_M_get() const noexcept
+      { return static_cast<const G_Dp*>(this)->G_M_payload.G_M_get(); }
+    };
+
+  template<typename G_Tp>
+    struct G_Optional_base<G_Tp, false, true> // trivial move ctor
+    : G_Optional_base_impl<G_Tp, G_Optional_base<G_Tp>>
+    {
+      // Constructors for disengaged optionals.
+      constexpr G_Optional_base() = default;
+
+      // Constructors for engaged optionals.
+      template<typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp, G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t, G_Args&&... g_args)
+	: G_M_payload(in_place, std::forward<G_Args>(g_args)...)
+	{ }
+
+      template<typename G_Up, typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp,
+					      std::initializer_list<G_Up>&,
+					      G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t,
+			std::initializer_list<G_Up> g_il,
+		       G_Args... g_args)
+	: G_M_payload(in_place, g_il, std::forward<G_Args>(g_args)...)
+	{ }
+
+      // Copy and move constructors.
+      constexpr G_Optional_base(const G_Optional_base& g_other)
+      : G_M_payload(g_other.G_M_payload.G_M_engaged, g_other.G_M_payload)
+      { }
+
+      constexpr G_Optional_base(G_Optional_base&& g_other) = default;
+
+      // Assignment operators.
+      G_Optional_base& operator=(const G_Optional_base&) = default;
+      G_Optional_base& operator=(G_Optional_base&&) = default;
+
+      G_Optional_payload<G_Tp> G_M_payload;
+    };
+
+  template<typename G_Tp>
+    struct G_Optional_base<G_Tp, true, false> // trivial copy ctor
+    : G_Optional_base_impl<G_Tp, G_Optional_base<G_Tp>>
+    {
+      // Constructors for disengaged optionals.
+      constexpr G_Optional_base() = default;
+
+      // Constructors for engaged optionals.
+      template<typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp, G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t, G_Args&&... g_args)
+	: G_M_payload(in_place, std::forward<G_Args>(g_args)...)
+	{ }
+
+      template<typename G_Up, typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp,
+					      std::initializer_list<G_Up>&,
+					      G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t,
+			std::initializer_list<G_Up> g_il,
+		       G_Args&&... g_args)
+	: G_M_payload(in_place, g_il, std::forward<G_Args>(g_args)...)
+	{ }
+
+      // Copy and move constructors.
+      constexpr G_Optional_base(const G_Optional_base& g_other) = default;
+
+      constexpr
+      G_Optional_base(G_Optional_base&& g_other)
+      noexcept(std::is_nothrow_move_constructible<G_Tp>::value)
+      : G_M_payload(g_other.G_M_payload.G_M_engaged,
+		   std::move(g_other.G_M_payload))
+      { }
+
+      // Assignment operators.
+      G_Optional_base& operator=(const G_Optional_base&) = default;
+      G_Optional_base& operator=(G_Optional_base&&) = default;
+
+      G_Optional_payload<G_Tp> G_M_payload;
+    };
+
+  template<typename G_Tp>
+    struct G_Optional_base<G_Tp, true, true> // trivial copy and move ctors
+    : G_Optional_base_impl<G_Tp, G_Optional_base<G_Tp>>
+    {
+      // Constructors for disengaged optionals.
+      constexpr G_Optional_base() = default;
+
+      // Constructors for engaged optionals.
+      template<typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp, G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t, G_Args&&... g_args)
+	: G_M_payload(in_place, std::forward<G_Args>(g_args)...)
+	{ }
+
+      template<typename G_Up, typename... G_Args,
+	       std::enable_if_t<std::is_constructible<G_Tp,
+					      std::initializer_list<G_Up>&,
+					      G_Args...>::value, bool> = false>
+	constexpr explicit
+	G_Optional_base(in_place_t,
+			std::initializer_list<G_Up> g_il,
+		       G_Args&&... g_args)
+	: G_M_payload(in_place, g_il, std::forward<G_Args>(g_args)...)
+	{ }
+
+      // Copy and move constructors.
+      constexpr G_Optional_base(const G_Optional_base& g_other) = default;
+      constexpr G_Optional_base(G_Optional_base&& g_other) = default;
+
+      // Assignment operators.
+      G_Optional_base& operator=(const G_Optional_base&) = default;
+      G_Optional_base& operator=(G_Optional_base&&) = default;
+
+      G_Optional_payload<G_Tp> G_M_payload;
+    };
+
+  template<typename>
+    struct g_is_optional : std::false_type {};
+
+  template<typename G_Tp>
+    struct g_is_optional<optional<G_Tp>> : std::true_type {};
+
+  template<typename G_Tp, typename G_Up>
+    using g_converts_from_optional
+      = g_converts_from_any_cvref<G_Tp, optional<G_Up>>;
+
+  template<typename G_Tp, typename G_Up>
+    using g_assigns_from_optional =
+      or_<std::is_assignable<G_Tp&, const optional<G_Up>&>,
+	    std::is_assignable<G_Tp&, optional<G_Up>&>,
+	    std::is_assignable<G_Tp&, const optional<G_Up>&&>,
+	    std::is_assignable<G_Tp&, optional<G_Up>&&>>;
+
+  /**
+    * @brief Class template for optional values.
+    */
+  template<typename G_Tp>
+    class optional
+    : private G_Optional_base<G_Tp>,
+      private G_Enable_copy_move<
+	// Copy constructor.
+	std::is_copy_constructible<G_Tp>::value,
+	// Copy assignment.
+	and_<std::is_copy_constructible<G_Tp>, std::is_copy_assignable<G_Tp>>::value,
+	// Move constructor.
+	std::is_move_constructible<G_Tp>::value,
+	// Move assignment.
+	and_<std::is_move_constructible<G_Tp>, std::is_move_assignable<G_Tp>>::value,
+	// Unique tag type.
+	optional<G_Tp>>
+    {
+      static_assert (g_is_valid_contained_type_for_optional<G_Tp>,
+		     "Given type not valid for an optional");
+
+    private:
+      using G_Base = G_Optional_base<G_Tp>;
+
+      // SFINAE helpers
+
+      template<typename G_From, typename = std::remove_cv_t<G_Tp>>
+	struct g_not_constructing_bool_from_optional
+	: std::true_type
+	{ };
+
+      template<typename G_From>
+	struct g_not_constructing_bool_from_optional<G_From, bool>
+	: not_<g_is_optional<g_remove_cvref_t<G_From>>>
+	{ };
+
+      template<typename G_From, typename = std::remove_cv_t<G_Tp>>
+	struct g_construct_from_contained_value
+	: not_<g_converts_from_optional<G_Tp, G_From>>
+	{ };
+
+      template<typename G_From>
+	struct g_construct_from_contained_value<G_From, bool>
+	: std::true_type
+	{ };
+
+      template<typename G_Up>
+	using g_not_self = not_<std::is_same<optional, g_remove_cvref_t<G_Up>>>;
+      template<typename G_Up>
+	using g_not_tag = not_<std::is_same<in_place_t, g_remove_cvref_t<G_Up>>>;
+
+    public:
+      using value_type = G_Tp;
+
+      constexpr optional() noexcept { }
+
+      constexpr optional(nullopt_t) noexcept { }
+
+      template<typename G_Up = std::remove_cv_t<G_Tp>,
+	       G_Requires<g_not_self<G_Up>, g_not_tag<G_Up>,
+			 std::is_constructible<G_Tp, G_Up>,
+			 std::is_convertible<G_Up, G_Tp>,
+			 g_not_constructing_bool_from_optional<G_Up>> = true>
+	constexpr
+	optional(G_Up&& g_t)
+	noexcept(std::is_nothrow_constructible<G_Tp, G_Up>::value)
+	: G_Base(in_place, std::forward<G_Up>(g_t)) { }
+
+      template<typename G_Up = std::remove_cv_t<G_Tp>,
+	       G_Requires<g_not_self<G_Up>, g_not_tag<G_Up>,
+			 std::is_constructible<G_Tp, G_Up>,
+			 not_<std::is_convertible<G_Up, G_Tp>>,
+			 g_not_constructing_bool_from_optional<G_Up>> = false>
+	explicit constexpr
+	optional(G_Up&& g_t)
+	noexcept(std::is_nothrow_constructible<G_Tp, G_Up>::value)
+	: G_Base(in_place, std::forward<G_Up>(g_t)) { }
+
+      template<typename G_Up,
+	       G_Requires<not_<std::is_same<G_Tp, G_Up>>,
+			 std::is_constructible<G_Tp, const G_Up&>,
+			 std::is_convertible<const G_Up&, G_Tp>,
+			 g_construct_from_contained_value<G_Up>> = true>
+	constexpr
+	optional(const optional<G_Up>& g_t)
+	noexcept(std::is_nothrow_constructible<G_Tp, const G_Up&>::value)
+	{
+	  if (g_t)
+	    emplace(g_t.G_M_fwd());
+	}
+
+      template<typename G_Up,
+	       G_Requires<not_<std::is_same<G_Tp, G_Up>>,
+			 std::is_constructible<G_Tp, const G_Up&>,
+			 not_<std::is_convertible<const G_Up&, G_Tp>>,
+			 g_construct_from_contained_value<G_Up>> = false>
+	explicit constexpr
+	optional(const optional<G_Up>& g_t)
+	noexcept(std::is_nothrow_constructible<G_Tp, const G_Up&>::value)
+	{
+	  if (g_t)
+	    emplace(g_t.G_M_fwd());
+	}
+
+      template<typename G_Up,
+	       G_Requires<not_<std::is_same<G_Tp, G_Up>>,
+			 std::is_constructible<G_Tp, G_Up>,
+			 std::is_convertible<G_Up, G_Tp>,
+			 g_construct_from_contained_value<G_Up>> = true>
+	constexpr
+	optional(optional<G_Up>&& g_t)
+	noexcept(std::is_nothrow_constructible<G_Tp, G_Up>::value)
+	{
+	  if (g_t)
+	    emplace(std::move(g_t).G_M_fwd());
+	}
+
+      template<typename G_Up,
+	       G_Requires<not_<std::is_same<G_Tp, G_Up>>,
+			 std::is_constructible<G_Tp, G_Up>,
+			 not_<std::is_convertible<G_Up, G_Tp>>,
+			 g_construct_from_contained_value<G_Up>> = false>
+	explicit constexpr
+	optional(optional<G_Up>&& g_t)
+	noexcept(std::is_nothrow_constructible<G_Tp, G_Up>::value)
+	{
+	  if (g_t)
+	    emplace(std::move(g_t).G_M_fwd());
+	}
+
+      template<typename... G_Args,
+	       G_Requires<std::is_constructible<G_Tp, G_Args...>> = false>
+	explicit constexpr
+	optional(in_place_t, G_Args&&... g_args)
+	noexcept(std::is_nothrow_constructible<G_Tp, G_Args...>::value)
+	: G_Base(in_place, std::forward<G_Args>(g_args)...) { }
+
+      template<typename G_Up, typename... G_Args,
+	       G_Requires<std::is_constructible<G_Tp,
+					  std::initializer_list<G_Up>&,
+					  G_Args...>> = false>
+	explicit constexpr
+	optional(in_place_t, std::initializer_list<G_Up> g_il, G_Args&&... g_args)
+	noexcept(std::is_nothrow_constructible<G_Tp, std::initializer_list<G_Up>&,
+					    G_Args...>::value)
+	: G_Base(in_place, g_il, std::forward<G_Args>(g_args)...) { }
+
+      // Assignment operators.
+      constexpr optional&
+      operator=(nullopt_t) noexcept
+      {
+	this->G_M_reset();
+	return *this;
+      }
+
+      template<typename G_Up = std::remove_cv_t<G_Tp>>
+        constexpr
+	std::enable_if_t<and_<g_not_self<G_Up>,
+			      not_<and_<std::is_scalar<G_Tp>,
+					std::is_same<G_Tp, std::decay_t<G_Up>>>>,
+			      std::is_constructible<G_Tp, G_Up>,
+			      std::is_assignable<G_Tp&, G_Up>>::value,
+		      optional&>
+	operator=(G_Up&& g_u)
+	noexcept(and_<std::is_nothrow_constructible<G_Tp, G_Up>,
+			 std::is_nothrow_assignable<G_Tp&, G_Up>>::value)
+	{
+	  if (this->G_M_is_engaged())
+	    this->G_M_get() = std::forward<G_Up>(g_u);
+	  else
+	    this->G_M_construct(std::forward<G_Up>(g_u));
+
+	  return *this;
+	}
+
+      template<typename G_Up>
+        constexpr
+	std::enable_if_t<and_<not_<std::is_same<G_Tp, G_Up>>,
+			    std::is_constructible<G_Tp, const G_Up&>,
+			    std::is_assignable<G_Tp&, const G_Up&>,
+			    not_<g_converts_from_optional<G_Tp, G_Up>>,
+			    not_<g_assigns_from_optional<G_Tp, G_Up>>>::value,
+		    optional&>
+	operator=(const optional<G_Up>& g_u)
+	noexcept(and_<std::is_nothrow_constructible<G_Tp, const G_Up&>,
+			 std::is_nothrow_assignable<G_Tp&, const G_Up&>>::value)
+	{
+	  if (g_u)
+	    {
+	      if (this->G_M_is_engaged())
+		this->G_M_get() = g_u.G_M_fwd();
+	      else
+		this->G_M_construct(g_u.G_M_fwd());
+	    }
+	  else
+	    {
+	      this->G_M_reset();
+	    }
+	  return *this;
+	}
+
+      template<typename G_Up>
+        constexpr
+	std::enable_if_t<and_<not_<std::is_same<G_Tp, G_Up>>,
+			      std::is_constructible<G_Tp, G_Up>,
+			      std::is_assignable<G_Tp&, G_Up>,
+			      not_<g_converts_from_optional<G_Tp, G_Up>>,
+			      not_<g_assigns_from_optional<G_Tp, G_Up>>>::value,
+			 optional&>
+	operator=(optional<G_Up>&& g_u)
+	noexcept(and_<std::is_nothrow_constructible<G_Tp, G_Up>,
+			 std::is_nothrow_assignable<G_Tp&, G_Up>>::value)
+	{
+	  if (g_u)
+	    {
+	      if (this->G_M_is_engaged())
+		this->G_M_get() = std::move(g_u).G_M_fwd();
+	      else
+		this->G_M_construct(std::move(g_u).G_M_fwd());
+	    }
+	  else
+	    {
+	      this->G_M_reset();
+	    }
+
+	  return *this;
+	}
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2746. Inconsistency between requirements for emplace between optional and variant
+      template<typename... G_Args>
+        constexpr
+	std::enable_if_t<std::is_constructible<G_Tp, G_Args...>::value, G_Tp&>
+	emplace(G_Args&&... g_args)
+	noexcept(std::is_nothrow_constructible<G_Tp, G_Args...>::value)
+	{
+	  this->G_M_reset();
+	  this->G_M_construct(std::forward<G_Args>(g_args)...);
+	  return this->G_M_get();
+	}
+
+      template<typename G_Up, typename... G_Args>
+        constexpr
+	std::enable_if_t<std::is_constructible<G_Tp, std::initializer_list<G_Up>&, G_Args...>::value,
+			 G_Tp&>
+	emplace(std::initializer_list<G_Up> g_il, G_Args&&... g_args)
+	noexcept(std::is_nothrow_constructible<G_Tp, std::initializer_list<G_Up>&,
+					    G_Args...>::value)
+	{
+	  this->G_M_reset();
+	  this->G_M_construct(g_il, std::forward<G_Args>(g_args)...);
+	  return this->G_M_get();
+	}
+
+      // Destructor is implicit, implemented in _Optional_base.
+
+      // Swap.
+      constexpr void
+      swap(optional& g_other)
+      noexcept(std::is_nothrow_move_constructible<G_Tp>::value
+	       && g_is_nothrow_swappable<G_Tp>::value)
+      {
+	using std::swap;
+
+	if (this->G_M_is_engaged() && g_other.G_M_is_engaged())
+	  swap(this->G_M_get(), g_other.G_M_get());
+	else if (this->G_M_is_engaged())
+	  {
+	    g_other.G_M_construct(std::move(this->G_M_get()));
+	    this->G_M_destruct();
+	  }
+	else if (g_other.G_M_is_engaged())
+	  {
+	    this->G_M_construct(std::move(g_other.G_M_get()));
+	    g_other.G_M_destruct();
+	  }
+      }
+
+      // Observers.
+      constexpr const G_Tp*
+      operator->() const noexcept
+      {
+	gccbackport_assert(this->G_M_is_engaged());
+	return std::addressof(this->G_M_get());
+      }
+
+      constexpr G_Tp*
+      operator->() noexcept
+      {
+	gccbackport_assert(this->G_M_is_engaged());
+	return std::addressof(this->G_M_get());
+      }
+
+      constexpr const G_Tp&
+      operator*() const& noexcept
+      {
+	gccbackport_assert(this->G_M_is_engaged());
+	return this->G_M_get();
+      }
+
+      constexpr G_Tp&
+      operator*()& noexcept
+      {
+	gccbackport_assert(this->G_M_is_engaged());
+	return this->G_M_get();
+      }
+
+      constexpr G_Tp&&
+      operator*()&& noexcept
+      {
+	gccbackport_assert(this->G_M_is_engaged());
+	return std::move(this->G_M_get());
+      }
+
+      constexpr const G_Tp&&
+      operator*() const&& noexcept
+      {
+	gccbackport_assert(this->G_M_is_engaged());
+	return std::move(this->G_M_get());
+      }
+
+      constexpr explicit operator bool() const noexcept
+      { return this->G_M_is_engaged(); }
+
+      constexpr bool has_value() const noexcept
+      { return this->G_M_is_engaged(); }
+
+      constexpr const G_Tp&
+      value() const&
+      {
+	if (this->G_M_is_engaged())
+	  return this->G_M_get();
+	g_throw_bad_optional_access();
+      }
+
+      constexpr G_Tp&
+      value()&
+      {
+	if (this->G_M_is_engaged())
+	  return this->G_M_get();
+	g_throw_bad_optional_access();
+      }
+
+      constexpr G_Tp&&
+      value()&&
+      {
+	if (this->G_M_is_engaged())
+	  return std::move(this->G_M_get());
+	g_throw_bad_optional_access();
+      }
+
+      constexpr const G_Tp&&
+      value() const&&
+      {
+	if (this->G_M_is_engaged())
+	  return std::move(this->G_M_get());
+	g_throw_bad_optional_access();
+      }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 4406. value_or return statement is inconsistent with Mandates
+      template<typename G_Up = std::remove_cv_t<G_Tp>>
+	constexpr std::remove_cv_t<G_Tp>
+	value_or(G_Up&& g_u) const&
+	{
+	  using G_Xp = std::remove_cv_t<G_Tp>;
+	  static_assert(std::is_convertible<const G_Tp&, G_Xp>::value, "");
+	  static_assert(std::is_convertible<G_Up, G_Xp>::value, "");
+
+	  if (this->G_M_is_engaged())
+	    return this->G_M_get();
+	  return std::forward<G_Up>(g_u);
+	}
+
+      template<typename G_Up = std::remove_cv_t<G_Tp>>
+	constexpr std::remove_cv_t<G_Tp>
+	value_or(G_Up&& g_u) &&
+	{
+	  using G_Xp = std::remove_cv_t<G_Tp>;
+	  static_assert(std::is_convertible<G_Tp, G_Xp>::value, "");
+	  static_assert(std::is_convertible<G_Up, G_Xp>::value, "");
+
+	  if (this->G_M_is_engaged())
+	    return std::move(this->G_M_get());
+	  return std::forward<G_Up>(g_u);
+	}
+
+      // [optional.monadic]
+
+      template<typename G_Fn>
+	constexpr auto
+	and_then(G_Fn&& g_f) &
+	{
+	  using G_Up = g_remove_cvref_t<g_invoke_result_t<G_Fn, G_Tp&>>;
+	  static_assert(g_is_optional<G_Up>::value,
+			"the function passed to std::optional<T>::and_then "
+			"must return a std::optional");
+	  if (has_value())
+	    return gcc::invoke(std::forward<G_Fn>(g_f), G_M_get());
+	  else
+	    return G_Up();
+	}
+
+      template<typename G_Fn>
+	constexpr auto
+	and_then(G_Fn&& g_f) const &
+	{
+	  using G_Up = g_remove_cvref_t<g_invoke_result_t<G_Fn, const G_Tp&>>;
+	  static_assert(g_is_optional<G_Up>::value,
+			"the function passed to std::optional<T>::and_then "
+			"must return a std::optional");
+	  if (has_value())
+	    return gcc::invoke(std::forward<G_Fn>(g_f), G_M_get());
+	  else
+	    return G_Up();
+	}
+
+      template<typename G_Fn>
+	constexpr auto
+	and_then(G_Fn&& g_f) &&
+	{
+	  using G_Up = g_remove_cvref_t<g_invoke_result_t<G_Fn, G_Tp>>;
+	  static_assert(g_is_optional<G_Up>::value,
+			"the function passed to std::optional<T>::and_then "
+			"must return a std::optional");
+	  if (has_value())
+	    return gcc::invoke(std::forward<G_Fn>(g_f), std::move(G_M_get()));
+	  else
+	    return G_Up();
+	}
+
+      template<typename G_Fn>
+	constexpr auto
+	and_then(G_Fn&& g_f) const &&
+	{
+	  using G_Up = g_remove_cvref_t<g_invoke_result_t<G_Fn, const G_Tp>>;
+	  static_assert(g_is_optional<G_Up>::value,
+			"the function passed to std::optional<T>::and_then "
+			"must return a std::optional");
+	  if (has_value())
+	    return gcc::invoke(std::forward<G_Fn>(g_f), std::move(G_M_get()));
+	  else
+	    return G_Up();
+	}
+
+      template<typename G_Fn>
+	constexpr auto
+	transform(G_Fn&& g_f) &
+	{
+	  using G_Up = std::remove_cv_t<g_invoke_result_t<G_Fn, G_Tp&>>;
+	  if (has_value())
+	    return optional<G_Up>(G_Optional_func<G_Fn>{g_f}, G_M_get());
+	  else
+	    return optional<G_Up>();
+	}
+
+      template<typename G_Fn>
+	constexpr auto
+	transform(G_Fn&& g_f) const &
+	{
+	  using G_Up = std::remove_cv_t<g_invoke_result_t<G_Fn, const G_Tp&>>;
+	  if (has_value())
+	    return optional<G_Up>(G_Optional_func<G_Fn>{g_f}, G_M_get());
+	  else
+	    return optional<G_Up>();
+	}
+
+      template<typename G_Fn>
+	constexpr auto
+	transform(G_Fn&& g_f) &&
+	{
+	  using G_Up = std::remove_cv_t<g_invoke_result_t<G_Fn, G_Tp>>;
+	  if (has_value())
+	    return optional<G_Up>(G_Optional_func<G_Fn>{g_f}, std::move(G_M_get()));
+	  else
+	    return optional<G_Up>();
+	}
+
+      template<typename G_Fn>
+	constexpr auto
+	transform(G_Fn&& g_f) const &&
+	{
+	  using G_Up = std::remove_cv_t<g_invoke_result_t<G_Fn, const G_Tp>>;
+	  if (has_value())
+	    return optional<G_Up>(G_Optional_func<G_Fn>{g_f}, std::move(G_M_get()));
+	  else
+	    return optional<G_Up>();
+	}
+
+      template<typename G_Fn,
+	       G_Requires<
+		 gcc::g_is_invocable<G_Fn>,
+		 std::is_copy_constructible<G_Tp>
+		 > = false>
+	constexpr optional
+	or_else(G_Fn&& g_f) const&
+	{
+	  using G_Up = g_invoke_result_t<G_Fn>;
+	  static_assert(std::is_same<g_remove_cvref_t<G_Up>, optional>::value,
+			"the function passed to std::optional<T>::or_else "
+			"must return a std::optional<T>");
+
+	  if (has_value())
+	    return *this;
+	  else
+	    return std::forward<G_Fn>(g_f)();
+	}
+
+      template<typename G_Fn,
+	       G_Requires<
+		 gcc::g_is_invocable<G_Fn>,
+		 std::is_move_constructible<G_Tp>
+		 > = false>
+	constexpr optional
+	or_else(G_Fn&& g_f) &&
+	{
+	  using G_Up = g_invoke_result_t<G_Fn>;
+	  static_assert(std::is_same<g_remove_cvref_t<G_Up>, optional>::value,
+			"the function passed to std::optional<T>::or_else "
+			"must return a std::optional<T>");
+
+	  if (has_value())
+	    return std::move(*this);
+	  else
+	    return std::forward<G_Fn>(g_f)();
+	}
+
+      constexpr void reset() noexcept { this->G_M_reset(); }
+
+    private:
+      using G_Base::G_M_get;
+
+      [[gnu::always_inline]]
+      constexpr G_Tp&
+      G_M_fwd() & noexcept
+      { return G_M_get(); }
+
+      [[gnu::always_inline]]
+      constexpr G_Tp&&
+      G_M_fwd() && noexcept
+      { return std::move(G_M_get()); }
+
+      [[gnu::always_inline]]
+      constexpr const G_Tp&
+      G_M_fwd() const& noexcept
+      { return G_M_get(); }
+
+      [[gnu::always_inline]]
+      constexpr const G_Tp&&
+      G_M_fwd() const&& noexcept
+      { return std::move(G_M_get()); }
+
+      template<typename G_Up> friend class optional;
+
+      template<typename G_Fn, typename G_Value>
+	explicit constexpr
+	optional(G_Optional_func<G_Fn> g_f, G_Value&& g_v)
+	{
+	  this->G_M_payload.G_M_apply(g_f, std::forward<G_Value>(g_v));
+	}
+    };
+
+  template<typename G_Tp>
+    constexpr G_Tp&
+    optional<G_Tp&>::value() const
+    {
+      if (G_M_val)
+	return *G_M_val;
+      g_throw_bad_optional_access();
+    }
+
+  template<typename G_Tp>
+    template<typename G_Up,
+	     typename G_Tp_,
+	     G_Requires<
+	       std::is_object<G_Tp_>,
+	       not_<std::is_array<G_Tp_>>
+	       >>
+      constexpr std::decay_t<G_Tp>
+      optional<G_Tp&>::value_or(G_Up&& g_u) const
+      {
+	using G_Xp = std::remove_cv_t<G_Tp>;
+	static_assert(std::is_convertible<G_Tp&, G_Xp>::value, "");
+	static_assert(std::is_convertible<G_Up, G_Xp>::value, "");
+	if (G_M_val)
+	  return *G_M_val;
+	return std::forward<G_Up>(g_u);
+      }
+
+  template<typename G_Tp>
+    template<typename G_Fn>
+      constexpr auto
+      optional<G_Tp&>::and_then(G_Fn&& g_f) const
+      {
+        using G_Up = g_remove_cvref_t<g_invoke_result_t<G_Fn, G_Tp&>>;
+        static_assert(g_is_optional<G_Up>::value,
+                      "the function passed to std::optional<T&>::and_then "
+                      "must return a std::optional");
+        if (has_value())
+          return gcc::invoke(std::forward<G_Fn>(g_f), *G_M_val);
+        else
+          return G_Up();
+      }
+
+  template<typename G_Tp>
+    template<typename G_Fn>
+      constexpr optional<std::remove_cv_t<g_invoke_result_t<G_Fn, G_Tp&>>>
+      optional<G_Tp&>::transform(G_Fn&& g_f) const
+      {
+        using G_Up = std::remove_cv_t<g_invoke_result_t<G_Fn, G_Tp&>>;
+        if (has_value())
+          return optional<G_Up>(G_Optional_func<G_Fn>{g_f}, *G_M_val);
+        else
+          return optional<G_Up>();
+      }
+
+  template<typename G_Tp>
+    template<typename G_Fn,
+	     G_Requires<g_is_invocable<G_Fn>>>
+      constexpr optional<G_Tp&>
+      optional<G_Tp&>::or_else(G_Fn&& g_f) const
+      {
+        static_assert(std::is_same<g_remove_cvref_t<g_invoke_result_t<G_Fn>>, optional>::value,
+                      "the function passed to std::optional<T&>::or_else "
+                      "must return a std::optional<T&>");
+        // _GLIBCXX_RESOLVE_LIB_DEFECTS
+        // 4367. Improve optional<T&>::or_else
+        if (has_value())
+          return *this;
+        else
+          return std::forward<G_Fn>(g_f)();
+      }
+
+  template<typename G_Tp>
+    template<typename G_Fn, typename G_Value>
+      constexpr
+      optional<G_Tp&>::optional(G_Optional_func<G_Fn> g_f, G_Value&& g_v)
+      {
+        G_Tp& g_r = gcc::invoke(std::forward<G_Fn>(g_f.G_M_f), std::forward<G_Value>(g_v));
+        G_M_val = std::addressof(g_r);
+      }
+
+  template<typename G_Tp>
+    using g_optional_relop_t =
+      std::enable_if_t<std::is_convertible<G_Tp, bool>::value, bool>;
+
+  template<typename G_Tp, typename G_Up>
+    using g_optional_eq_t = g_optional_relop_t<
+      decltype(std::declval<const G_Tp&>() == std::declval<const G_Up&>())
+      >;
+
+  template<typename G_Tp, typename G_Up>
+    using g_optional_ne_t = g_optional_relop_t<
+      decltype(std::declval<const G_Tp&>() != std::declval<const G_Up&>())
+      >;
+
+  template<typename G_Tp, typename G_Up>
+    using g_optional_lt_t = g_optional_relop_t<
+      decltype(std::declval<const G_Tp&>() < std::declval<const G_Up&>())
+      >;
+
+  template<typename G_Tp, typename G_Up>
+    using g_optional_gt_t = g_optional_relop_t<
+      decltype(std::declval<const G_Tp&>() > std::declval<const G_Up&>())
+      >;
+
+  template<typename G_Tp, typename G_Up>
+    using g_optional_le_t = g_optional_relop_t<
+      decltype(std::declval<const G_Tp&>() <= std::declval<const G_Up&>())
+      >;
+
+  template<typename G_Tp, typename G_Up>
+    using g_optional_ge_t = g_optional_relop_t<
+      decltype(std::declval<const G_Tp&>() >= std::declval<const G_Up&>())
+      >;
+
+  // Comparisons between optional values.
+  template<typename G_Tp, typename G_Up>
+    constexpr auto
+    operator==(const optional<G_Tp>& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_eq_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value() != g_rhs.has_value())
+	return false;
+      if (!g_lhs.has_value())
+	return true;
+      return *g_lhs == *g_rhs;
+    }
+
+  template<typename G_Tp, typename G_Up>
+    constexpr auto
+    operator!=(const optional<G_Tp>& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_ne_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value() != g_rhs.has_value())
+	return true;
+      if (!g_lhs.has_value())
+	return false;
+      return *g_lhs != *g_rhs;
+    }
+
+  template<typename G_Tp, typename G_Up>
+    constexpr auto
+    operator<(const optional<G_Tp>& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_lt_t<G_Tp, G_Up>
+    {
+      if (!g_rhs.has_value())
+	return false;
+      if (!g_lhs.has_value())
+	return true;
+      return *g_lhs < *g_rhs;
+    }
+
+  template<typename G_Tp, typename G_Up>
+    constexpr auto
+    operator>(const optional<G_Tp>& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_gt_t<G_Tp, G_Up>
+    {
+      if (!g_lhs.has_value())
+	return false;
+      if (!g_rhs.has_value())
+	return true;
+      return *g_lhs > *g_rhs;
+    }
+
+  template<typename G_Tp, typename G_Up>
+    constexpr auto
+    operator<=(const optional<G_Tp>& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_le_t<G_Tp, G_Up>
+    {
+      if (!g_lhs.has_value())
+	return true;
+      if (!g_rhs.has_value())
+	return false;
+      return *g_lhs <= *g_rhs;
+    }
+
+  template<typename G_Tp, typename G_Up>
+    constexpr auto
+    operator>=(const optional<G_Tp>& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_ge_t<G_Tp, G_Up>
+    {
+      if (!g_rhs.has_value())
+	return true;
+      if (!g_lhs.has_value())
+	return false;
+      return *g_lhs >= *g_rhs;
+    }
+
+#ifdef __cpp_lib_three_way_comparison
+  template<typename G_Tp, std::three_way_comparable_with<G_Tp> G_Up>
+    [[nodiscard]]
+    constexpr std::compare_three_way_result_t<G_Tp, G_Up>
+    operator<=>(const optional<G_Tp>& g_x, const optional<G_Up>& g_y)
+    {
+      return g_x && g_y ? *g_x <=> *g_y : bool(g_x) <=> bool(g_y);
+    }
+#endif
+
+  // Comparisons with nullopt.
+  template<typename G_Tp>
+    [[nodiscard]]
+    constexpr bool
+    operator==(const optional<G_Tp>& g_lhs, nullopt_t) noexcept
+    { return !g_lhs; }
+
+#ifdef __cpp_lib_three_way_comparison
+  template<typename G_Tp>
+    [[nodiscard]]
+    constexpr std::strong_ordering
+    operator<=>(const optional<G_Tp>& g_x, nullopt_t) noexcept
+    { return bool(g_x) <=> false; }
+#else
+  template<typename G_Tp>
+    constexpr bool
+    operator==(nullopt_t, const optional<G_Tp>& g_rhs) noexcept
+    { return !g_rhs; }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator!=(const optional<G_Tp>& g_lhs, nullopt_t) noexcept
+    { return static_cast<bool>(g_lhs); }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator!=(nullopt_t, const optional<G_Tp>& g_rhs) noexcept
+    { return static_cast<bool>(g_rhs); }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator<(const optional<G_Tp>& /* __lhs */, nullopt_t) noexcept
+    { return false; }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator<(nullopt_t, const optional<G_Tp>& g_rhs) noexcept
+    { return static_cast<bool>(g_rhs); }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator>(const optional<G_Tp>& g_lhs, nullopt_t) noexcept
+    { return static_cast<bool>(g_lhs); }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator>(nullopt_t, const optional<G_Tp>& /* __rhs */) noexcept
+    { return false; }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator<=(const optional<G_Tp>& g_lhs, nullopt_t) noexcept
+    { return !g_lhs; }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator<=(nullopt_t, const optional<G_Tp>& /* __rhs */) noexcept
+    { return true; }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator>=(const optional<G_Tp>& /* __lhs */, nullopt_t) noexcept
+    { return true; }
+
+  template<typename G_Tp>
+    constexpr bool
+    operator>=(nullopt_t, const optional<G_Tp>& g_rhs) noexcept
+    { return !g_rhs; }
+#endif // three-way-comparison
+
+  // Comparisons with value type.
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Up>>> = false>
+    constexpr auto
+    operator== [[nodiscard]] (const optional<G_Tp>& g_lhs, const G_Up& g_rhs)
+    -> g_optional_eq_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value())
+	return *g_lhs == g_rhs;
+      return false;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Tp>>> = false>
+    constexpr auto
+    operator== [[nodiscard]] (const G_Tp& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_eq_t<G_Tp, G_Up>
+    {
+      if (g_rhs.has_value())
+	return g_lhs == *g_rhs;
+      return false;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Up>>> = false>
+    constexpr auto
+    operator!= [[nodiscard]] (const optional<G_Tp>& g_lhs, const G_Up& g_rhs)
+    -> g_optional_ne_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value())
+	return *g_lhs != g_rhs;
+      return true;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Tp>>> = false>
+    constexpr auto
+    operator!= [[nodiscard]] (const G_Tp& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_ne_t<G_Tp, G_Up>
+    {
+      if (g_rhs.has_value())
+	return g_lhs != *g_rhs;
+      return true;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Up>>> = false>
+    constexpr auto
+    operator< [[nodiscard]] (const optional<G_Tp>& g_lhs, const G_Up& g_rhs)
+    -> g_optional_lt_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value())
+	return *g_lhs < g_rhs;
+      return true;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Tp>>> = false>
+    constexpr auto
+    operator< [[nodiscard]] (const G_Tp& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_lt_t<G_Tp, G_Up>
+    {
+      if (g_rhs.has_value())
+	return g_lhs < *g_rhs;
+      return false;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Up>>> = false>
+    constexpr auto
+    operator> [[nodiscard]] (const optional<G_Tp>& g_lhs, const G_Up& g_rhs)
+    -> g_optional_gt_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value())
+	return *g_lhs > g_rhs;
+      return false;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Tp>>> = false>
+    constexpr auto
+    operator> [[nodiscard]] (const G_Tp& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_gt_t<G_Tp, G_Up>
+    {
+      if (g_rhs.has_value())
+	return g_lhs > *g_rhs;
+      return true;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Up>>> = false>
+    constexpr auto
+    operator<= [[nodiscard]] (const optional<G_Tp>& g_lhs, const G_Up& g_rhs)
+    -> g_optional_le_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value())
+	return *g_lhs <= g_rhs;
+      return true;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Tp>>> = false>
+    constexpr auto
+    operator<= [[nodiscard]] (const G_Tp& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_le_t<G_Tp, G_Up>
+    {
+      if (g_rhs.has_value())
+	return g_lhs <= *g_rhs;
+      return false;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Up>>> = false>
+    constexpr auto
+    operator>= [[nodiscard]] (const optional<G_Tp>& g_lhs, const G_Up& g_rhs)
+    -> g_optional_ge_t<G_Tp, G_Up>
+    {
+      if (g_lhs.has_value())
+	return *g_lhs >= g_rhs;
+      return false;
+    }
+
+  template<typename G_Tp, typename G_Up,
+	   G_Requires<not_<g_is_optional<G_Tp>>> = false>
+    constexpr auto
+    operator>= [[nodiscard]] (const G_Tp& g_lhs, const optional<G_Up>& g_rhs)
+    -> g_optional_ge_t<G_Tp, G_Up>
+    {
+      if (g_rhs.has_value())
+	return g_lhs >= *g_rhs;
+      return true;
+    }
+
+#ifdef __cpp_lib_three_way_comparison
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 3746. optional's spaceship with U with a type derived from optional
+  // causes infinite constraint meta-recursion
+  template<typename G_Tp>
+    concept g_is_derived_from_optional = requires (const G_Tp& g_t) {
+      []<typename G_Up>(const optional<G_Up>&){ }(g_t);
+    };
+
+  template<typename G_Tp, typename G_Up>
+    requires (!g_is_derived_from_optional<G_Up>)
+      && requires { typename std::compare_three_way_result_t<G_Tp, G_Up>; }
+      && std::three_way_comparable_with<G_Tp, G_Up>
+    constexpr std::compare_three_way_result_t<G_Tp, G_Up>
+    operator<=> [[nodiscard]] (const optional<G_Tp>& g_x, const G_Up& g_v)
+    { return bool(g_x) ? *g_x <=> g_v : std::strong_ordering::less; }
+#endif
+
+  // Swap and creation functions.
+
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2748. swappable traits for optionals
+  template<typename G_Tp>
+    constexpr
+    inline std::enable_if_t<std::is_move_constructible<G_Tp>::value && g_is_swappable<G_Tp>::value>
+    swap(optional<G_Tp>& g_lhs, optional<G_Tp>& g_rhs)
+    noexcept(noexcept(g_lhs.swap(g_rhs)))
+    { g_lhs.swap(g_rhs); }
+
+  // We deviate from standard, that do not declared separate swap overload
+  // from optional<T&>.
+  template<typename G_Tp>
+    constexpr void
+    swap(optional<G_Tp&>& g_lhs, optional<G_Tp&>& g_rhs) noexcept
+    { g_lhs.swap(g_rhs); }
+
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2766. Swapping non-swappable types
+  template<typename G_Tp>
+    std::enable_if_t<!(std::is_move_constructible<G_Tp>::value && g_is_swappable<G_Tp>::value)>
+    swap(optional<G_Tp>&, optional<G_Tp>&) = delete;
+
+  template<int = 0, typename G_Tp>
+    constexpr
+    std::enable_if_t<std::is_constructible<std::decay_t<G_Tp>, G_Tp>::value,
+		optional<std::decay_t<G_Tp>>>
+    make_optional(G_Tp&& g_t)
+    noexcept(std::is_nothrow_constructible<optional<std::decay_t<G_Tp>>, G_Tp>::value)
+    { return optional<std::decay_t<G_Tp>>( std::forward<G_Tp>(g_t) ); }
+
+  template<typename G_Tp, typename... G_Args>
+    constexpr
+    std::enable_if_t<std::is_constructible<G_Tp, G_Args...>::value,
+		optional<G_Tp>>
+    make_optional(G_Args&&... g_args)
+    noexcept(std::is_nothrow_constructible<G_Tp, G_Args...>::value)
+    { return optional<G_Tp>( in_place, std::forward<G_Args>(g_args)... ); }
+
+  template<typename G_Tp, typename G_Up, typename... G_Args>
+    constexpr
+    std::enable_if_t<std::is_constructible<G_Tp, std::initializer_list<G_Up>&, G_Args...>::value,
+		optional<G_Tp>>
+    make_optional(std::initializer_list<G_Up> g_il, G_Args&&... g_args)
+    noexcept(std::is_nothrow_constructible<G_Tp, std::initializer_list<G_Up>&, G_Args...>::value)
+    { return optional<G_Tp>( in_place, g_il, std::forward<G_Args>(g_args)... ); }
+
+  // Hash.
+
+  template<typename G_Tp, typename G_Up = std::remove_const_t<G_Tp>>
+    struct g_optional_hash
+    {
+#if __cplusplus < 202002L
+      using result_type = size_t;
+      using argument_type = optional<G_Tp>;
+#endif
+
+      size_t
+      operator()(const optional<G_Tp>& g_t) const
+      noexcept(noexcept(std::hash<G_Up>{}(*g_t)))
+      {
+	// We pick an arbitrary hash for disengaged optionals which hopefully
+	// usual values of _Tp won't typically hash to.
+	constexpr size_t g_magic_disengaged_hash = static_cast<size_t>(-3333);
+	return g_t ? std::hash<G_Up>{}(*g_t) : g_magic_disengaged_hash;
+      }
+    };
+
+#if __cpp_deduction_guides >= 201606
+  template <typename G_Tp> optional(G_Tp) -> optional<G_Tp>;
+#endif
+
+} // namespace gcc
+
+namespace std {
+
+  template<typename G_Tp>
+    struct hash<gcc::optional<G_Tp>>
+    // hash for optional<T&> is disabled because is_hash_enabled_for<T&> is false
+    : public std::conditional_t<
+        gcc::g_is_hash_enabled_for<std::remove_const_t<G_Tp>>::value,
+        gcc::g_optional_hash<G_Tp>,
+	gcc::g_hash_not_enabled<G_Tp>>
+    { };
+
+  /// @}
+
+} // namespace std
+
+#endif // GCC_BACKPORT_GLIBCXX_OPTIONAL
diff --git a/gcc/stdbackport/optionalfwd b/gcc/stdbackport/optionalfwd
new file mode 100644
index 000000000000..53c9999f6341
--- /dev/null
+++ b/gcc/stdbackport/optionalfwd
@@ -0,0 +1,36 @@
+// Forward declarations for backported <optional> -*- C++ -*-
+
+// Copyright (C) 2013-2026 Free Software Foundation, Inc.
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef GCC_BACKPORT_GLIBCXX_OPTIONALFWD
+#define GCC_BACKPORT_GLIBCXX_OPTIONALFWD 1
+
+namespace gcc {
+
+  template<typename G_Tp>
+    class optional;
+
+} // namespace gcc
+
+#endif // GCC_BACKPORT_GLIBCXX_OPTIONAL
-- 
2.55.0



More information about the Gcc-rust mailing list