aboutsummaryrefslogtreecommitdiff
path: root/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat')
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/bit.h185
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/functional.h50
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/bit.h230
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/constructors.h100
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/exception.h56
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/storage.h847
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/type_traits.h112
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h137
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/memory.h66
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/optional.h475
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/type_traits.h509
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/utility.h118
-rw-r--r--third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/version.h79
13 files changed, 2964 insertions, 0 deletions
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/bit.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/bit.h
new file mode 100644
index 000000000..1e9309417
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/bit.h
@@ -0,0 +1,185 @@
+// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_BIT_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_BIT_H_
+
+#include <cstring>
+#include <limits>
+
+#include "internal/bit.h"
+#include "memory.h"
+#include "version.h"
+
+#if __has_include(<bit>) && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#include <bit>
+
+#endif //__has_include(<bit>) && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+namespace cpp20 {
+
+#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::bit_cast;
+
+#else // Use builtin to provide constexpr bit_cast.
+
+#if defined(__has_builtin) && !defined(LIB_STDCOMPAT_NO_BUILTIN_BITCAST)
+#if __has_builtin(__builtin_bit_cast)
+
+template <typename To, typename From>
+constexpr std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable<To>::value &&
+ std::is_trivially_copyable<From>::value,
+ To>
+bit_cast(const From& from) {
+ return __builtin_bit_cast(To, from);
+}
+
+// Since there are two #if checks, using #else would require code duplication.
+// Define a temporary internal macro to indicate that bit_cast was defined.
+#define LIB_STDCOMPAT_BIT_CAST_DEFINED_
+
+#endif // __has_builtin(__builtin_bit_cast)
+#endif // defined(__has_builtin) && !defined(LIB_STDCOMPAT_NO_BUILTIN_BITCAST)
+
+// Use memcpy instead, not constexpr though.
+#ifndef LIB_STDCOMPAT_BIT_CAST_DEFINED_
+
+#define LIB_STDCOMPAT_NONCONSTEXPR_BITCAST 1
+
+template <typename To, typename From>
+std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable<To>::value &&
+ std::is_trivially_copyable<From>::value,
+ To>
+bit_cast(const From& from) {
+ std::aligned_storage_t<sizeof(To)> uninitialized_to;
+ std::memcpy(static_cast<void*>(&uninitialized_to),
+ static_cast<const void*>(cpp17::addressof(from)), sizeof(To));
+ return *reinterpret_cast<const To*>(&uninitialized_to);
+}
+
+#endif // LIB_STDCOMPAT_BIT_CAST_DEFINED_
+
+#undef LIB_STDCOMPAT_BIT_CAST_DEFINED_
+
+#endif // __cpp_lib_bit_cast >= 201806L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::countl_one;
+using std::countl_zero;
+using std::countr_one;
+using std::countr_zero;
+using std::popcount;
+using std::rotl;
+using std::rotr;
+
+#else
+
+template <class T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, int> countr_zero(T x) noexcept {
+ if (x == 0) {
+ return std::numeric_limits<T>::digits;
+ }
+
+ return internal::count_zeros_from_right(x);
+}
+
+template <class T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, int> countl_zero(T x) noexcept {
+ if (x == 0) {
+ return std::numeric_limits<T>::digits;
+ }
+
+ return internal::count_zeros_from_left(x);
+}
+
+template <class T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, int> countl_one(T x) noexcept {
+ return countl_zero(static_cast<T>(~x));
+}
+
+template <class T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, int> countr_one(T x) noexcept {
+ return countr_zero(static_cast<T>(~x));
+}
+
+template <class T>
+[[gnu::warn_unused_result]] constexpr std::enable_if_t<std::is_unsigned<T>::value, T> rotl(
+ T x, int s) noexcept {
+ return internal::rotl(x, s);
+}
+
+template <class T>
+[[gnu::warn_unused_result]] constexpr std::enable_if_t<std::is_unsigned<T>::value, T> rotr(
+ T x, int s) noexcept {
+ return internal::rotr(x, s);
+}
+
+template <class T>
+constexpr int popcount(T x) noexcept {
+ return internal::popcount(x);
+}
+
+#endif
+
+#if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::bit_ceil;
+using std::bit_floor;
+using std::bit_width;
+using std::has_single_bit;
+
+#else // Provide polyfills for power of two bit functions.
+
+template <typename T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, bool> has_single_bit(T value) {
+ return popcount(value) == static_cast<T>(1);
+}
+
+template <typename T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, T> bit_width(T value) {
+ return internal::bit_width(value);
+}
+
+template <typename T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, T> bit_ceil(T value) {
+ if (value <= 1) {
+ return T(1);
+ }
+ return internal::bit_ceil<T>(value);
+}
+
+template <typename T>
+constexpr std::enable_if_t<std::is_unsigned<T>::value, T> bit_floor(T value) {
+ if (value == 0) {
+ return 0;
+ }
+ return internal::bit_floor(value);
+}
+
+#endif // __cpp_lib_int_pow2 >= 202002L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::endian;
+
+#else // Provide polyfill for endian enum.
+
+enum class endian {
+ little = 0x11771E,
+ big = 0xB16,
+ native = internal::native_endianess<little, big>(),
+};
+
+#endif
+
+} // namespace cpp20
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_BIT_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/functional.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/functional.h
new file mode 100644
index 000000000..34d44e0d5
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/functional.h
@@ -0,0 +1,50 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_FUNCTIONAL_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_FUNCTIONAL_H_
+
+#include "internal/functional.h"
+
+namespace cpp20 {
+
+// This version is always constexpr-qualified, with no other changes from C++17.
+
+#if defined(__cpp_lib_invoke) && defined(__cpp_lib_constexpr_functional) && \
+ __cpp_lib_invoke >= 201411L && __cpp_lib_constexpr_functional >= 201907L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::invoke;
+
+#else // Provide invoke() polyfill
+
+template <typename F, typename... Args>
+constexpr cpp17::invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(
+ cpp17::is_nothrow_invocable_v<F, Args...>) {
+ return ::cpp17::internal::invoke(std::forward<F>(f), std::forward<Args>(args)...);
+}
+
+#endif // __cpp_lib_invoke >= 201411L && __cpp_lib_constexpr_functional >= 201907L &&
+ // !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::bind_front;
+
+#else // Provide bind_front() polyfill
+
+template <typename F, typename... Args>
+constexpr ::cpp20::internal::front_binder_t<F, Args...> bind_front(F&& f, Args&&... args) noexcept(
+ cpp17::is_nothrow_constructible_v<::cpp20::internal::front_binder_t<F, Args...>,
+ cpp17::in_place_t, F, Args...>) {
+ return ::cpp20::internal::front_binder_t<F, Args...>(cpp17::in_place, std::forward<F>(f),
+ std::forward<Args>(args)...);
+}
+
+#endif // __cpp_lib_bind_front >= 201907L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp20
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_FUNCTIONAL_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/bit.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/bit.h
new file mode 100644
index 000000000..92b33a633
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/bit.h
@@ -0,0 +1,230 @@
+// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_BIT_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_BIT_H_
+
+#include <limits>
+#include <type_traits>
+
+#include "../type_traits.h"
+
+namespace cpp20 {
+namespace internal {
+
+// Helper for exclusing specific char types when char is considered unsigned by the compiler.
+template <typename T>
+struct is_bit_type
+ : std::integral_constant<
+ bool, std::is_unsigned<T>::value && !std::is_same<bool, T>::value &&
+ !std::is_same<T, char>::value && !std::is_same<T, char16_t>::value &&
+ !std::is_same<T, char32_t>::value && !std::is_same<T, wchar_t>::value> {};
+
+// Rotation implementation.
+// Only internal for usage in implementation of certain methods.
+template <class T>
+[[gnu::warn_unused_result]] constexpr std::enable_if_t<is_bit_type<T>::value, T> rotl(
+ T x, int s) noexcept {
+ const auto digits = std::numeric_limits<T>::digits;
+ const auto rotate_by = s % digits;
+
+ if (rotate_by > 0) {
+ return static_cast<T>((x << rotate_by) | (x >> (digits - rotate_by)));
+ }
+
+ if (rotate_by < 0) {
+ return static_cast<T>((x >> -rotate_by) | (x << (digits + rotate_by)));
+ }
+
+ return x;
+}
+
+template <class T>
+[[gnu::warn_unused_result]] constexpr std::enable_if_t<is_bit_type<T>::value, T> rotr(
+ T x, int s) noexcept {
+ int digits = std::numeric_limits<T>::digits;
+ int rotate_by = s % digits;
+
+ if (rotate_by > 0) {
+ return static_cast<T>((x >> rotate_by) | (x << (digits - rotate_by)));
+ }
+
+ if (rotate_by < 0) {
+ return rotl(x, -rotate_by);
+ }
+
+ return x;
+}
+
+// Overloads for intrinsics.
+// Precondition: |value| != 0.
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(T) <= sizeof(unsigned), int>
+count_zeros_from_right(T value) noexcept {
+ return __builtin_ctz(static_cast<unsigned>(value));
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned) < sizeof(T) &&
+ sizeof(T) <= sizeof(unsigned long),
+ int>
+count_zeros_from_right(T value) noexcept {
+ return __builtin_ctzl(static_cast<unsigned long>(value));
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned long) < sizeof(T) &&
+ sizeof(T) <= sizeof(unsigned long long),
+ int>
+count_zeros_from_right(T value) noexcept {
+ return __builtin_ctzll(static_cast<unsigned long long>(value));
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned long long) < sizeof(T), int>
+count_zeros_from_right(T value) noexcept {
+ int count = 0;
+ int iter_count = 0;
+ const unsigned long long max_digits = std::numeric_limits<unsigned long long>::digits;
+
+ for (int slot = 0; slot * max_digits < std::numeric_limits<T>::digits; ++slot) {
+ const unsigned long long chunk =
+ static_cast<unsigned long long>(internal::rotr(value, (slot)*max_digits));
+ iter_count = (chunk == 0) ? static_cast<int>(max_digits) : count_zeros_from_right(chunk);
+ count += iter_count;
+ if (iter_count != max_digits) {
+ break;
+ }
+ }
+ return count - static_cast<int>(std::numeric_limits<T>::digits % max_digits);
+}
+
+template <typename T, typename U,
+ typename std::enable_if<sizeof(T) >= sizeof(U), bool>::type = true>
+struct digit_diff
+ : std::integral_constant<T, std::numeric_limits<T>::digits - std::numeric_limits<U>::digits> {};
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(T) <= sizeof(unsigned), int>
+count_zeros_from_left(T value) noexcept {
+ return __builtin_clz(static_cast<unsigned>(value)) -
+ static_cast<int>(digit_diff<unsigned, T>::value);
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned) < sizeof(T) &&
+ sizeof(T) <= sizeof(unsigned long),
+ int>
+count_zeros_from_left(T value) noexcept {
+ return __builtin_clzl(static_cast<unsigned long>(value)) -
+ static_cast<int>(digit_diff<unsigned long, T>::value);
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned long) < sizeof(T) &&
+ sizeof(T) <= sizeof(unsigned long long),
+ int>
+count_zeros_from_left(T value) noexcept {
+ return __builtin_clzll(static_cast<unsigned long long>(value)) -
+ static_cast<int>(digit_diff<unsigned long long, T>::value);
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned long long) < sizeof(T), int>
+count_zeros_from_left(T value) noexcept {
+ int count = 0;
+ int iter_count = 0;
+ const unsigned int max_digits = std::numeric_limits<unsigned long long>::digits;
+
+ for (int slot = 0; slot * max_digits < std::numeric_limits<T>::digits; ++slot) {
+ const unsigned long long chunk =
+ static_cast<unsigned long long>(internal::rotl(value, (slot + 1) * max_digits));
+ iter_count = (chunk == 0) ? static_cast<int>(max_digits) : count_zeros_from_left(chunk);
+ count += iter_count;
+ if (iter_count != max_digits) {
+ break;
+ }
+ }
+ return count - static_cast<int>(std::numeric_limits<T>::digits % max_digits);
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(T) <= sizeof(unsigned), int> popcount(
+ T value) noexcept {
+ return __builtin_popcount(static_cast<unsigned>(value));
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned) < sizeof(T) &&
+ sizeof(T) <= sizeof(unsigned long),
+ int>
+popcount(T value) noexcept {
+ return __builtin_popcountl(static_cast<unsigned long>(value));
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned long) < sizeof(T) &&
+ sizeof(T) <= sizeof(unsigned long long),
+ int>
+popcount(T value) noexcept {
+ return __builtin_popcountll(static_cast<unsigned long long>(value));
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && sizeof(unsigned long long) < sizeof(T), int>
+popcount(T value) noexcept {
+ int accumulated_count = 0;
+ while (value != 0) {
+ accumulated_count += popcount(static_cast<unsigned long long>(value));
+ value >>= std::numeric_limits<unsigned long long>::digits;
+ }
+ return accumulated_count;
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value, T> bit_width(T value) {
+ const T zeros_left =
+ (value == 0) ? std::numeric_limits<T>::digits : static_cast<T>(count_zeros_from_left(value));
+ return std::numeric_limits<T>::digits - zeros_left;
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && !std::is_same<T, decltype(+T())>::value, T>
+bit_ceil(T value) {
+ unsigned ub_offset = std::numeric_limits<unsigned>::digits - std::numeric_limits<T>::digits;
+ return static_cast<T>(1 << (bit_width(static_cast<T>(value - 1)) + ub_offset) >> ub_offset);
+}
+
+// When there is no integer promotion.
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value && std::is_same<T, decltype(+T())>::value, T>
+bit_ceil(T value) {
+ auto width = bit_width(value - 1);
+ if (!cpp20::is_constant_evaluated() && width == std::numeric_limits<T>::digits) {
+ __builtin_abort();
+ }
+ return static_cast<T>(1) << width;
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_bit_type<T>::value, T> bit_floor(T value) {
+ return static_cast<T>(T(1) << (bit_width(value) - T(1)));
+}
+
+template <unsigned little, unsigned big>
+constexpr unsigned native_endianess() {
+ auto curr = __BYTE_ORDER__;
+ if (curr == __ORDER_LITTLE_ENDIAN__) {
+ return little;
+ }
+ if (curr == __ORDER_BIG_ENDIAN__) {
+ return big;
+ }
+ return 0x404;
+}
+
+} // namespace internal
+} // namespace cpp20
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_BIT_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/constructors.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/constructors.h
new file mode 100644
index 000000000..e86f2f108
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/constructors.h
@@ -0,0 +1,100 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_CONSTRUCTORS_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_CONSTRUCTORS_H_
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+namespace cpp17 {
+namespace internal {
+
+// Mixin that implicitly deletes the subclass default constructor when type T
+// is not default constructible.
+template <typename T, bool = std::is_default_constructible<T>::value>
+struct modulate_default_constructor {};
+template <typename T>
+struct modulate_default_constructor<T, false> {
+ constexpr modulate_default_constructor() = delete;
+};
+
+// Mixin that implicitly deletes the subclass copy constructor when type T is
+// not copy constructible.
+template <std::size_t Index, typename T, bool = std::is_copy_constructible<T>::value>
+struct modulate_copy_constructor {};
+template <std::size_t Index, typename T>
+struct modulate_copy_constructor<Index, T, false> {
+ constexpr modulate_copy_constructor() = default;
+ constexpr modulate_copy_constructor(const modulate_copy_constructor&) = delete;
+ constexpr modulate_copy_constructor& operator=(const modulate_copy_constructor&) = default;
+ constexpr modulate_copy_constructor(modulate_copy_constructor&&) = default;
+ constexpr modulate_copy_constructor& operator=(modulate_copy_constructor&&) = default;
+};
+
+// Mixin that implicitly deletes the subclass copy assignment operator when type
+// T is not copy assignable.
+template <std::size_t Index, typename T, bool = std::is_copy_assignable<T>::value>
+struct modulate_copy_assignment {};
+template <std::size_t Index, typename T>
+struct modulate_copy_assignment<Index, T, false> {
+ constexpr modulate_copy_assignment() = default;
+ constexpr modulate_copy_assignment(const modulate_copy_assignment&) = default;
+ constexpr modulate_copy_assignment& operator=(const modulate_copy_assignment&) = delete;
+ constexpr modulate_copy_assignment(modulate_copy_assignment&&) = default;
+ constexpr modulate_copy_assignment& operator=(modulate_copy_assignment&&) = default;
+};
+
+// Mixin that implicitly deletes the subclass move constructor when type T is
+// not move constructible.
+template <std::size_t Index, typename T, bool = std::is_move_constructible<T>::value>
+struct modulate_move_constructor {};
+template <std::size_t Index, typename T>
+struct modulate_move_constructor<Index, T, false> {
+ constexpr modulate_move_constructor() = default;
+ constexpr modulate_move_constructor(const modulate_move_constructor&) = default;
+ constexpr modulate_move_constructor& operator=(const modulate_move_constructor&) = default;
+ constexpr modulate_move_constructor(modulate_move_constructor&&) = delete;
+ constexpr modulate_move_constructor& operator=(modulate_move_constructor&&) = default;
+};
+
+// Mixin that implicitly deletes the subclass move assignment operator when type
+// T is not move assignable.
+template <std::size_t Index, typename T, bool = std::is_move_assignable<T>::value>
+struct modulate_move_assignment {};
+template <std::size_t Index, typename T>
+struct modulate_move_assignment<Index, T, false> {
+ constexpr modulate_move_assignment() = default;
+ constexpr modulate_move_assignment(const modulate_move_assignment&) = default;
+ constexpr modulate_move_assignment& operator=(const modulate_move_assignment&) = default;
+ constexpr modulate_move_assignment(modulate_move_assignment&&) = default;
+ constexpr modulate_move_assignment& operator=(modulate_move_assignment&&) = delete;
+};
+
+// Utility that takes an index sequence and an equally sized parameter pack and
+// mixes in each of the above copy/move construction/assignment modulators for
+// each type in Ts. The indices are used to avoid duplicate direct base errors
+// by ensuring that each mixin type is unique, even when there are duplicate
+// types within the parameter pack Ts.
+template <typename IndexSequence, typename... Ts>
+struct modulate_copy_and_move_index;
+
+template <std::size_t... Is, typename... Ts>
+struct modulate_copy_and_move_index<std::index_sequence<Is...>, Ts...>
+ : modulate_copy_constructor<Is, Ts>...,
+ modulate_copy_assignment<Is, Ts>...,
+ modulate_move_constructor<Is, Ts>...,
+ modulate_move_assignment<Is, Ts>... {};
+
+// Mixin that modulates the subclass copy/move constructors and assignment
+// operators based on the copy/move characteristics of each type in Ts.
+template <typename... Ts>
+struct modulate_copy_and_move
+ : modulate_copy_and_move_index<std::index_sequence_for<Ts...>, Ts...> {};
+
+} // namespace internal
+} // namespace cpp17
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_CONSTRUCTORS_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/exception.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/exception.h
new file mode 100644
index 000000000..74f4e8c08
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/exception.h
@@ -0,0 +1,56 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_EXCEPTION_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_EXCEPTION_H_
+
+#include <exception>
+
+#include "../type_traits.h"
+
+namespace cpp17 {
+namespace internal {
+
+// When exceptions are enabled, will generate an exception of the right type, when disabled will
+// simply abort execution.
+//
+// Note: both clang and gcc support gnu::unused, which makes it a portable alternative for
+// [[maybe_unused]].
+template <typename T,
+ typename std::enable_if<std::is_base_of<std::exception, T>::value, bool>::type = true>
+[[noreturn]] inline constexpr void throw_or_abort([[gnu::unused]] const char* reason) {
+#if defined(__cpp_exceptions) && __cpp_exceptions >= 199711L
+ throw T(reason);
+#else
+ __builtin_abort();
+#endif
+}
+
+template <typename T>
+inline constexpr void throw_or_abort_if_any_impl(const char* reason, bool should_abort) {
+ if (should_abort) {
+ throw_or_abort<T>(reason);
+ }
+}
+
+template <typename T, typename... AbortIf>
+inline constexpr void throw_or_abort_if_any_impl(const char* reason, bool head, AbortIf... tail) {
+ if (head) {
+ throw_or_abort<T>(reason);
+ }
+ throw_or_abort_if_any_impl<T>(reason, tail...);
+}
+
+template <typename T, typename... AbortIf>
+inline constexpr void throw_or_abort_if_any(const char* reason, AbortIf... abort_if) {
+ static_assert(sizeof...(AbortIf) > 0, "Must provide an |abort_if| clause.");
+ static_assert(cpp17::conjunction_v<std::is_same<bool, AbortIf>...>,
+ "|abort_if| arguments must be boolean.");
+ throw_or_abort_if_any_impl<T>(reason, abort_if...);
+}
+
+} // namespace internal
+} // namespace cpp17
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_EXCEPTION_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/storage.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/storage.h
new file mode 100644
index 000000000..16c64d559
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/storage.h
@@ -0,0 +1,847 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_STORAGE_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_STORAGE_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#include "utility.h"
+
+namespace cpp17 {
+namespace internal {
+
+// Type tag to select overloads based on type T.
+template <typename T>
+struct type_tag {
+ using type = T;
+};
+
+// Type tag to select overloads based on index Index.
+template <std::size_t Index>
+struct index_tag {
+ static constexpr std::size_t index = Index;
+};
+
+// Type tag to select trivial initialization.
+enum trivial_init_t { trivial_init_v };
+
+// Type tag to select default initialization.
+enum default_init_t { default_init_v };
+
+// Type tag to select conditional initialization.
+enum maybe_init_t { maybe_init_v };
+
+// Represents the pair (T, Index) in the type system.
+template <typename T, std::size_t Index>
+struct type_index {};
+
+// Represents whether a type is trivially/non-trivially destructible.
+enum class destructor_class {
+ trivial,
+ non_trivial,
+};
+
+// Represents whether a type is trivially/non-trivially copyable.
+enum class copy_class {
+ trivial,
+ non_trivial,
+};
+
+// Represents whether a type is trivially/non-trivially movable.
+enum class move_class {
+ trivial,
+ non_trivial,
+};
+
+// Represents the full complement of move/copy/destruct classes for a type.
+template <destructor_class DestructorClass, copy_class CopyClass, move_class MoveClass>
+struct storage_class {};
+
+template <typename... Ts>
+using make_storage_class =
+ storage_class<is_trivially_destructible_v<Ts...> ? destructor_class::trivial
+ : destructor_class::non_trivial,
+ is_trivially_copyable_v<Ts...> ? copy_class::trivial : copy_class::non_trivial,
+ is_trivially_movable_v<Ts...> ? move_class::trivial : move_class::non_trivial>;
+
+// A trivial type for the empty alternative of union-based storage.
+struct empty_type {};
+
+// Index type used to track the active variant. Tracking uses zero-based
+// indices. Empty is denoted by the maximum representable value.
+using index_type = std::size_t;
+
+// Index denoting that no user-specified variant is active. Take care not to
+// ODR-use this value.
+constexpr index_type empty_index = std::numeric_limits<index_type>::max();
+
+#ifdef NDEBUG
+#define LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT __builtin_unreachable
+#else
+#define LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT __builtin_abort
+#endif
+
+// Base type for lazy-initialized union storage types. This type implements a
+// recursive union of the element types in Ts. Specializations handle the
+// recursive and terminal cases, and the different storage requirements for
+// trivially/non-trivially destructible types.
+template <destructor_class, typename...>
+union storage_base;
+
+// Non-trivial terminal case.
+template <>
+union storage_base<destructor_class::non_trivial, type_index<empty_type, empty_index>> {
+ storage_base() : empty{} {}
+
+ template <typename... Args>
+ storage_base(type_tag<empty_type>, Args&&...) : empty{} {}
+ template <typename... Args>
+ storage_base(index_tag<empty_index>, Args&&...) : empty{} {}
+
+ // Non-trivial destructor.
+ ~storage_base() {}
+
+ storage_base(const storage_base&) = default;
+ storage_base(storage_base&&) = default;
+ storage_base& operator=(const storage_base&) = default;
+ storage_base& operator=(storage_base&&) = default;
+
+ void construct_at(std::size_t index, const storage_base&) {
+ if (index == empty_index) {
+ new (&empty) empty_type{};
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+ void construct_at(std::size_t index, storage_base&&) {
+ if (index == empty_index) {
+ new (&empty) empty_type{};
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ void assign_at(std::size_t index, const storage_base& other) {
+ if (index == empty_index) {
+ empty = other.empty;
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+ void assign_at(std::size_t index, storage_base&& other) {
+ if (index == empty_index) {
+ empty = std::move(other.empty);
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ void swap_at(std::size_t index, storage_base& other) {
+ if (index == empty_index) {
+ using std::swap;
+ swap(empty, other.empty);
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ template <typename... Args>
+ std::size_t construct(type_tag<empty_type>, Args&&...) {
+ new (&empty) empty_type{};
+ return empty_index;
+ }
+ template <typename... Args>
+ std::size_t construct(index_tag<empty_index>, Args&&...) {
+ new (&empty) empty_type{};
+ return empty_index;
+ }
+
+ void reset(std::size_t index) {
+ if (index == empty_index) {
+ empty.empty_type::~empty_type();
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ empty_type& get(type_tag<empty_type>) { return empty; }
+ const empty_type& get(type_tag<empty_type>) const { return empty; }
+ empty_type& get(index_tag<empty_index>) { return empty; }
+ const empty_type& get(index_tag<empty_index>) const { return empty; }
+
+ std::size_t index(type_tag<empty_type>) const { return empty_index; }
+
+ template <typename V>
+ bool visit(std::size_t, V&&) {
+ return false;
+ }
+ template <typename V>
+ bool visit(std::size_t, V&&) const {
+ return false;
+ }
+
+ empty_type empty;
+};
+
+// Trivial terminal case.
+template <>
+union storage_base<destructor_class::trivial, type_index<empty_type, empty_index>> {
+ constexpr storage_base() : empty{} {}
+
+ template <typename... Args>
+ constexpr storage_base(type_tag<empty_type>, Args&&...) : empty{} {}
+ template <typename... Args>
+ constexpr storage_base(index_tag<empty_index>, Args&&...) : empty{} {}
+
+ // Trivial destructor.
+ ~storage_base() = default;
+
+ constexpr storage_base(const storage_base&) = default;
+ constexpr storage_base(storage_base&&) = default;
+ constexpr storage_base& operator=(const storage_base&) = default;
+ constexpr storage_base& operator=(storage_base&&) = default;
+
+ constexpr void construct_at(std::size_t index, const storage_base&) {
+ if (index == empty_index) {
+ new (&empty) empty_type{};
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+ constexpr void construct_at(std::size_t index, storage_base&&) {
+ if (index == empty_index) {
+ new (&empty) empty_type{};
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ constexpr void assign_at(std::size_t index, const storage_base& other) {
+ if (index == empty_index) {
+ empty = other.empty;
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+ constexpr void assign_at(std::size_t index, storage_base&& other) {
+ if (index == empty_index) {
+ empty = std::move(other.empty);
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ constexpr void swap_at(std::size_t index, storage_base& other) {
+ if (index == empty_index) {
+ using std::swap;
+ swap(empty, other.empty);
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ template <typename... Args>
+ constexpr std::size_t construct(type_tag<empty_type>, Args&&...) {
+ new (&empty) empty_type{};
+ return empty_index;
+ }
+ template <typename... Args>
+ constexpr std::size_t construct(index_tag<empty_index>, Args&&...) {
+ new (&empty) empty_type{};
+ return empty_index;
+ }
+
+ constexpr void reset(std::size_t index) {
+ if (index == empty_index) {
+ empty.empty_type::~empty_type();
+ } else {
+ LIB_STDCOMPAT_INTERNAL_UNREACHABLE_OR_ABORT();
+ }
+ }
+
+ constexpr empty_type& get(type_tag<empty_type>) { return empty; }
+ constexpr const empty_type& get(type_tag<empty_type>) const { return empty; }
+ constexpr empty_type& get(index_tag<empty_index>) { return empty; }
+ constexpr const empty_type& get(index_tag<empty_index>) const { return empty; }
+
+ constexpr std::size_t index(type_tag<empty_type>) const { return empty_index; }
+
+ template <typename V>
+ constexpr bool visit(std::size_t, V&&) {
+ return false;
+ }
+ template <typename V>
+ constexpr bool visit(std::size_t, V&&) const {
+ return false;
+ }
+
+ empty_type empty;
+};
+
+template <typename T, std::size_t Index, typename... Ts, std::size_t... Is>
+union storage_base<destructor_class::non_trivial, type_index<T, Index>, type_index<Ts, Is>...> {
+ storage_base() : empty{} {}
+
+ template <typename... Args>
+ storage_base(type_tag<T>, Args&&... args) : value(std::forward<Args>(args)...) {}
+ template <typename... Args>
+ storage_base(index_tag<Index>, Args&&... args) : value(std::forward<Args>(args)...) {}
+
+ template <typename U, typename... Args>
+ storage_base(type_tag<U>, Args&&... args) : rest(type_tag<U>{}, std::forward<Args>(args)...) {}
+ template <std::size_t OtherIndex, typename... Args>
+ storage_base(index_tag<OtherIndex>, Args&&... args)
+ : rest(index_tag<OtherIndex>{}, std::forward<Args>(args)...) {}
+
+ // Non-trivial destructor.
+ ~storage_base() {}
+
+ // Trival copy/move construction and assignment.
+ storage_base(const storage_base&) = default;
+ storage_base(storage_base&&) = default;
+ storage_base& operator=(const storage_base&) = default;
+ storage_base& operator=(storage_base&&) = default;
+
+ void construct_at(std::size_t index, const storage_base& other) {
+ if (index == Index) {
+ new (&value) T{other.value};
+ } else {
+ rest.construct_at(index, other.rest);
+ }
+ }
+ void construct_at(std::size_t index, storage_base&& other) {
+ if (index == Index) {
+ new (&value) T{std::move(other.value)};
+ } else {
+ rest.construct_at(index, std::move(other.rest));
+ }
+ }
+
+ void assign_at(std::size_t index, const storage_base& other) {
+ if (index == Index) {
+ value = other.value;
+ } else {
+ rest.assign_at(index, other.rest);
+ }
+ }
+ void assign_at(std::size_t index, storage_base&& other) {
+ if (index == Index) {
+ value = std::move(other.value);
+ } else {
+ rest.assign_at(index, std::move(other.rest));
+ }
+ }
+
+ void swap_at(std::size_t index, storage_base& other) {
+ if (index == Index) {
+ using std::swap;
+ swap(value, other.value);
+ } else {
+ rest.swap_at(index, other.rest);
+ }
+ }
+
+ template <typename... Args>
+ std::size_t construct(type_tag<T>, Args&&... args) {
+ new (&value) T(std::forward<Args>(args)...);
+ return Index;
+ }
+ template <typename U, typename... Args>
+ std::size_t construct(type_tag<U>, Args&&... args) {
+ return rest.construct(type_tag<U>{}, std::forward<Args>(args)...);
+ }
+ template <typename... Args>
+ std::size_t construct(index_tag<Index>, Args&&... args) {
+ new (&value) T(std::forward<Args>(args)...);
+ return Index;
+ }
+ template <std::size_t OtherIndex, typename... Args>
+ std::size_t construct(index_tag<OtherIndex>, Args&&... args) {
+ return rest.construct(index_tag<OtherIndex>{}, std::forward<Args>(args)...);
+ }
+
+ void reset(std::size_t index) {
+ if (index == Index) {
+ value.~T();
+ } else {
+ rest.reset(index);
+ }
+ }
+
+ T& get(type_tag<T>) { return value; }
+ const T& get(type_tag<T>) const { return value; }
+ template <typename U>
+ U& get(type_tag<U>) {
+ return rest.get(type_tag<U>{});
+ }
+ template <typename U>
+ const U& get(type_tag<U>) const {
+ return rest.get(type_tag<U>{});
+ }
+ T& get(index_tag<Index>) { return value; }
+ const T& get(index_tag<Index>) const { return value; }
+ template <std::size_t OtherIndex>
+ auto& get(index_tag<OtherIndex>) {
+ return rest.get(index_tag<OtherIndex>{});
+ }
+ template <std::size_t OtherIndex>
+ const auto& get(index_tag<OtherIndex>) const {
+ return rest.get(index_tag<OtherIndex>{});
+ }
+
+ std::size_t index(type_tag<T>) const { return Index; }
+ template <typename U>
+ std::size_t index(type_tag<U>) const {
+ return rest.index(type_tag<U>{});
+ }
+
+ template <typename V>
+ bool visit(std::size_t index, V&& visitor) {
+ if (index == Index) {
+ std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
+ return true;
+ } else {
+ return rest.visit(index, std::forward<V>(visitor));
+ }
+ }
+ template <typename V>
+ bool visit(std::size_t index, V&& visitor) const {
+ if (index == Index) {
+ std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
+ return true;
+ } else {
+ return rest.visit(index, std::forward<V>(visitor));
+ }
+ }
+
+ empty_type empty;
+ T value;
+ storage_base<destructor_class::non_trivial, type_index<Ts, Is>...> rest;
+};
+
+template <typename T, std::size_t Index, typename... Ts, std::size_t... Is>
+union storage_base<destructor_class::trivial, type_index<T, Index>, type_index<Ts, Is>...> {
+ constexpr storage_base() : empty{} {}
+
+ template <typename... Args>
+ constexpr storage_base(type_tag<T>, Args&&... args) : value(std::forward<Args>(args)...) {}
+ template <typename... Args>
+ constexpr storage_base(index_tag<Index>, Args&&... args) : value(std::forward<Args>(args)...) {}
+
+ template <typename U, typename... Args>
+ constexpr storage_base(type_tag<U>, Args&&... args)
+ : rest(type_tag<U>{}, std::forward<Args>(args)...) {}
+ template <std::size_t OtherIndex, typename... Args>
+ constexpr storage_base(index_tag<OtherIndex>, Args&&... args)
+ : rest(index_tag<OtherIndex>{}, std::forward<Args>(args)...) {}
+
+ // Trivial destructor.
+ ~storage_base() = default;
+
+ // Trival copy/move construction and assignment.
+ constexpr storage_base(const storage_base&) = default;
+ constexpr storage_base(storage_base&&) = default;
+ constexpr storage_base& operator=(const storage_base&) = default;
+ constexpr storage_base& operator=(storage_base&&) = default;
+
+ constexpr void construct_at(std::size_t index, const storage_base& other) {
+ if (index == Index) {
+ new (&value) T{other.value};
+ } else {
+ rest.construct_at(index, other.rest);
+ }
+ }
+ constexpr void construct_at(std::size_t index, storage_base&& other) {
+ if (index == Index) {
+ new (&value) T{std::move(other.value)};
+ } else {
+ rest.construct_at(index, std::move(other.rest));
+ }
+ }
+
+ constexpr void assign_at(std::size_t index, const storage_base& other) {
+ if (index == Index) {
+ value = other.value;
+ } else {
+ rest.assign_at(index, other.rest);
+ }
+ }
+ constexpr void assign_at(std::size_t index, storage_base&& other) {
+ if (index == Index) {
+ value = std::move(other.value);
+ } else {
+ rest.assign_at(index, std::move(other.rest));
+ }
+ }
+
+ constexpr void swap_at(std::size_t index, storage_base& other) {
+ if (index == Index) {
+ using std::swap;
+ swap(value, other.value);
+ } else {
+ rest.swap_at(index, other.rest);
+ }
+ }
+
+ template <typename... Args>
+ constexpr std::size_t construct(type_tag<T>, Args&&... args) {
+ new (&value) T(std::forward<Args>(args)...);
+ return Index;
+ }
+ template <typename U, typename... Args>
+ constexpr std::size_t construct(type_tag<U>, Args&&... args) {
+ return rest.construct(type_tag<U>{}, std::forward<Args>(args)...);
+ }
+ template <typename... Args>
+ constexpr std::size_t construct(index_tag<Index>, Args&&... args) {
+ new (&value) T(std::forward<Args>(args)...);
+ return Index;
+ }
+ template <std::size_t OtherIndex, typename... Args>
+ constexpr std::size_t construct(index_tag<OtherIndex>, Args&&... args) {
+ return rest.construct(index_tag<OtherIndex>{}, std::forward<Args>(args)...);
+ }
+
+ constexpr void reset(std::size_t) {}
+
+ constexpr T& get(type_tag<T>) { return value; }
+ constexpr const T& get(type_tag<T>) const { return value; }
+ template <typename U>
+ constexpr U& get(type_tag<U>) {
+ return rest.get(type_tag<U>{});
+ }
+ template <typename U>
+ constexpr const U& get(type_tag<U>) const {
+ return rest.get(type_tag<U>{});
+ }
+ constexpr T& get(index_tag<Index>) { return value; }
+ constexpr const T& get(index_tag<Index>) const { return value; }
+ template <std::size_t OtherIndex>
+ constexpr auto& get(index_tag<OtherIndex>) {
+ return rest.get(index_tag<OtherIndex>{});
+ }
+ template <std::size_t OtherIndex>
+ constexpr const auto& get(index_tag<OtherIndex>) const {
+ return rest.get(index_tag<OtherIndex>{});
+ }
+
+ constexpr std::size_t index(type_tag<T>) const { return Index; }
+ template <typename U>
+ constexpr std::size_t index(type_tag<U>) const {
+ return rest.index(type_tag<U>{});
+ }
+
+ template <typename V>
+ constexpr bool visit(std::size_t index, V&& visitor) {
+ if (index == Index) {
+ std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
+ return true;
+ } else {
+ return rest.visit(index, std::forward<V>(visitor));
+ }
+ }
+ template <typename V>
+ constexpr bool visit(std::size_t index, V&& visitor) const {
+ if (index == Index) {
+ std::forward<V>(visitor)(type_tag<T>{}, index_tag<Index>{}, this);
+ return true;
+ } else {
+ return rest.visit(index, std::forward<V>(visitor));
+ }
+ }
+
+ empty_type empty;
+ T value;
+ storage_base<destructor_class::trivial, type_index<Ts, Is>...> rest;
+};
+
+// Lazy-initialized union storage type that tracks the index of the active
+// variant.
+template <destructor_class, typename...>
+class indexed_storage;
+
+template <destructor_class DestructorClass, typename... Ts, std::size_t... Is>
+class indexed_storage<DestructorClass, type_index<Ts, Is>...> {
+ private:
+ using base_type =
+ storage_base<DestructorClass, type_index<Ts, Is>..., type_index<empty_type, empty_index>>;
+
+ public:
+ static constexpr bool nothrow_default_constructible =
+ std::is_nothrow_default_constructible<first_t<Ts...>>::value;
+ static constexpr bool nothrow_move_constructible =
+ conjunction_v<std::is_nothrow_move_constructible<Ts>...>;
+ static constexpr bool nothrow_move_assignable =
+ conjunction_v<std::is_nothrow_move_assignable<Ts>...>;
+
+ constexpr indexed_storage() = default;
+
+ constexpr indexed_storage(trivial_init_t) : indexed_storage{} {}
+
+ constexpr indexed_storage(default_init_t) : index_{0}, base_{index_tag<0>{}} {}
+
+ // Only used by trivial copy/move types.
+ constexpr indexed_storage(const indexed_storage& other) = default;
+ constexpr indexed_storage& operator=(const indexed_storage& other) = default;
+ constexpr indexed_storage(indexed_storage&& other) = default;
+ constexpr indexed_storage& operator=(indexed_storage&& other) = default;
+
+ template <typename T, typename... Args>
+ constexpr indexed_storage(type_tag<T>, Args&&... args)
+ : base_(type_tag<T>{}, std::forward<Args>(args)...) {
+ index_ = base_.index(type_tag<T>{});
+ }
+ template <std::size_t Index, typename... Args>
+ constexpr indexed_storage(index_tag<Index>, Args&&... args)
+ : index_{Index}, base_(index_tag<Index>{}, std::forward<Args>(args)...) {}
+
+ constexpr indexed_storage(maybe_init_t, const indexed_storage& other)
+ : index_{other.index()}, base_{} {
+ base_.construct_at(other.index(), other.base_);
+ }
+ constexpr indexed_storage(maybe_init_t, indexed_storage&& other)
+ : index_{other.index()}, base_{} {
+ base_.construct_at(other.index(), std::move(other.base_));
+ }
+
+ ~indexed_storage() = default;
+
+ constexpr index_type index() const { return index_; }
+ constexpr bool is_empty() const { return index() == empty_index; }
+ template <typename T>
+ constexpr bool has_value(type_tag<T>) const {
+ return index() == base_.index(type_tag<T>{});
+ }
+ template <std::size_t Index>
+ constexpr bool has_value(index_tag<Index>) const {
+ return index() == Index;
+ }
+
+ template <typename T>
+ constexpr auto& get(type_tag<T>) {
+ return base_.get(type_tag<T>{});
+ }
+ template <typename T>
+ constexpr const auto& get(type_tag<T>) const {
+ return base_.get(type_tag<T>{});
+ }
+ template <std::size_t Index>
+ constexpr auto& get(index_tag<Index>) {
+ return base_.get(index_tag<Index>{});
+ }
+ template <std::size_t Index>
+ constexpr const auto& get(index_tag<Index>) const {
+ return base_.get(index_tag<Index>{});
+ }
+
+ template <typename T, typename... Args>
+ constexpr void construct(type_tag<T>, Args&&... args) {
+ index_ = base_.construct(type_tag<T>{}, std::forward<Args>(args)...);
+ }
+ template <std::size_t Index, typename... Args>
+ constexpr void construct(index_tag<Index>, Args&&... args) {
+ index_ = base_.construct(index_tag<Index>{}, std::forward<Args>(args)...);
+ }
+
+ constexpr void assign(const indexed_storage& other) {
+ if (index() == other.index()) {
+ base_.assign_at(index_, other.base_);
+ } else {
+ reset();
+ base_.construct_at(other.index_, other.base_);
+ index_ = other.index_;
+ }
+ }
+ constexpr void assign(indexed_storage&& other) {
+ if (index() == other.index()) {
+ base_.assign_at(index_, std::move(other.base_));
+ } else {
+ reset();
+ base_.construct_at(other.index_, std::move(other.base_));
+ index_ = other.index_;
+ }
+ }
+
+ template <typename V>
+ constexpr bool visit(V&& visitor) {
+ return base_.visit(index_, std::forward<V>(visitor));
+ }
+ template <typename V>
+ constexpr bool visit(V&& visitor) const {
+ return base_.visit(index_, std::forward<V>(visitor));
+ }
+
+ constexpr void swap(indexed_storage& other) {
+ if (index() == other.index()) {
+ // Swap directly when the variants are the same, including empty.
+ base_.swap_at(index_, other.base_);
+ } else {
+ // Swap when the variants are different, including one being empty.
+ // This approach avoids GCC -Wmaybe-uninitialized warnings by
+ // initializing and accessing |temp| unconditionally within a
+ // conditional scope. The alternative, using the maybe_init_t
+ // constructor confuses GCC because it doesn't understand that the
+ // index checks prevent uninitialized access.
+ auto do_swap = [](indexed_storage& a, indexed_storage& b) {
+ return a.base_.visit(a.index_, [&a, &b](auto, auto index_tag_v, auto* element) {
+ indexed_storage temp{index_tag_v, std::move(element->value)};
+ a.reset();
+
+ a.base_.construct_at(b.index_, std::move(b.base_));
+ a.index_ = b.index_;
+ b.reset();
+
+ b.base_.construct_at(temp.index_, std::move(temp.base_));
+ b.index_ = temp.index_;
+ temp.reset();
+ });
+ };
+
+ // The visitor above returns false when the first argument is empty
+ // and no action is taken. In that case, the other order is tried to
+ // complete the half-empty swap.
+ do_swap(*this, other) || do_swap(other, *this);
+ }
+ }
+
+ // Destroys the active variant. Does nothing when already empty.
+ constexpr void reset() {
+ base_.reset(index_);
+ index_ = empty_index;
+ }
+
+ private:
+ index_type index_{empty_index};
+ base_type base_;
+};
+
+// Internal variant storage type used by cpp17::optional and cpp17::variant.
+// Specializations of this type select trivial vs. non-trivial copy/move
+// construction, assignment operators, and destructor based on the storage class
+// of the types in Ts.
+template <typename StorageClass, typename... Ts>
+struct storage;
+
+template <typename... Ts, std::size_t... Is>
+struct storage<storage_class<destructor_class::trivial, copy_class::trivial, move_class::trivial>,
+ type_index<Ts, Is>...>
+ : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
+ using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
+ using base_type::base_type;
+ constexpr storage() = default;
+};
+
+template <typename... Ts, std::size_t... Is>
+struct storage<
+ storage_class<destructor_class::trivial, copy_class::non_trivial, move_class::trivial>,
+ type_index<Ts, Is>...> : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
+ using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
+ using base_type::base_type;
+
+ ~storage() = default;
+ constexpr storage() = default;
+
+ constexpr storage(const storage& other) : base_type{maybe_init_v, other} {}
+
+ constexpr storage& operator=(const storage& other) {
+ this->assign(other);
+ return *this;
+ }
+
+ constexpr storage(storage&&) = default;
+ constexpr storage& operator=(storage&&) = default;
+};
+
+template <typename... Ts, std::size_t... Is>
+struct storage<
+ storage_class<destructor_class::trivial, copy_class::trivial, move_class::non_trivial>,
+ type_index<Ts, Is>...> : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
+ using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
+ using base_type::base_type;
+
+ ~storage() = default;
+ constexpr storage() = default;
+ constexpr storage(const storage&) = default;
+ constexpr storage& operator=(const storage&) = default;
+
+ constexpr storage(storage&& other) noexcept(base_type::nothrow_move_constructible)
+ : base_type{maybe_init_v, std::move(other)} {}
+
+ constexpr storage& operator=(storage&& other) noexcept(base_type::nothrow_move_assignable) {
+ this->assign(std::move(other));
+ return *this;
+ }
+};
+
+template <typename... Ts, std::size_t... Is>
+struct storage<
+ storage_class<destructor_class::trivial, copy_class::non_trivial, move_class::non_trivial>,
+ type_index<Ts, Is>...> : indexed_storage<destructor_class::trivial, type_index<Ts, Is>...> {
+ using base_type = indexed_storage<destructor_class::trivial, type_index<Ts, Is>...>;
+ using base_type::base_type;
+
+ ~storage() = default;
+ constexpr storage() = default;
+
+ constexpr storage(const storage& other) : base_type{maybe_init_v, other} {}
+
+ constexpr storage& operator=(const storage& other) {
+ this->assign(other);
+ return *this;
+ }
+
+ constexpr storage(storage&& other) noexcept(base_type::nothrow_move_constructible)
+ : base_type{maybe_init_v, std::move(other)} {}
+
+ constexpr storage& operator=(storage&& other) noexcept(base_type::nothrow_move_assignable) {
+ this->assign(std::move(other));
+ return *this;
+ }
+};
+
+// Specialization for non-trivially movable/copyable types. Types with a non-
+// trivial destructor are always non-trivially movable/copyable.
+template <copy_class CopyClass, move_class MoveClass, typename... Ts, std::size_t... Is>
+struct storage<storage_class<destructor_class::non_trivial, CopyClass, MoveClass>,
+ type_index<Ts, Is>...>
+ : indexed_storage<destructor_class::non_trivial, type_index<Ts, Is>...> {
+ using base_type = indexed_storage<destructor_class::non_trivial, type_index<Ts, Is>...>;
+ using base_type::base_type;
+
+ ~storage() { this->reset(); }
+
+ constexpr storage() = default;
+
+ constexpr storage(const storage& other) : base_type{maybe_init_v, other} {}
+
+ constexpr storage& operator=(const storage& other) {
+ this->assign(other);
+ return *this;
+ }
+
+ constexpr storage(storage&& other) noexcept(base_type::nothrow_move_constructible)
+ : base_type{maybe_init_v, std::move(other)} {}
+
+ constexpr storage& operator=(storage&& other) noexcept(base_type::nothrow_move_assignable) {
+ this->assign(std::move(other));
+ return *this;
+ }
+};
+
+template <typename... Ts, std::size_t... Is>
+constexpr auto make_storage(std::index_sequence<Is...>) {
+ return storage<make_storage_class<Ts...>, type_index<Ts, Is>...>{};
+}
+
+template <typename... Ts>
+using storage_type = decltype(make_storage<Ts...>(std::index_sequence_for<Ts...>{}));
+
+} // namespace internal
+} // namespace cpp17
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_STORAGE_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/type_traits.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/type_traits.h
new file mode 100644
index 000000000..dced28d9f
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/type_traits.h
@@ -0,0 +1,112 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_TYPE_TRAITS_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_TYPE_TRAITS_H_
+
+#include <type_traits>
+
+namespace cpp17 {
+namespace internal {
+
+template <typename T>
+static constexpr bool is_reference_wrapper = false;
+template <typename T>
+static constexpr bool is_reference_wrapper<std::reference_wrapper<T>> = true;
+
+// These are from [func.require] ΒΆ 1.1-7
+template <typename MemFn, typename Class, typename T>
+static constexpr bool invoke_pmf_base = std::is_member_function_pointer<MemFn Class::*>::value&&
+ std::is_base_of<Class, std::remove_reference_t<T>>::value;
+
+template <typename MemFn, typename Class, typename T>
+static constexpr bool invoke_pmf_refwrap = std::is_member_function_pointer<MemFn Class::*>::value&&
+ is_reference_wrapper<std::remove_cv_t<std::remove_reference_t<T>>>;
+
+template <typename MemFn, typename Class, typename T>
+static constexpr bool invoke_pmf_other =
+ std::is_member_function_pointer<MemFn Class::*>::value && !invoke_pmf_base<MemFn, Class, T> &&
+ !invoke_pmf_refwrap<MemFn, Class, T>;
+
+template <typename MemObj, typename Class, typename T>
+static constexpr bool invoke_pmd_base = std::is_member_object_pointer<MemObj Class::*>::value&&
+ std::is_base_of<Class, std::remove_reference_t<T>>::value;
+
+template <typename MemObj, typename Class, typename T>
+static constexpr bool invoke_pmd_refwrap = std::is_member_object_pointer<MemObj Class::*>::value&&
+ is_reference_wrapper<std::remove_cv_t<std::remove_reference_t<T>>>;
+
+template <typename MemObj, typename Class, typename T>
+static constexpr bool invoke_pmd_other =
+ std::is_member_object_pointer<MemObj Class::*>::value && !invoke_pmd_base<MemObj, Class, T> &&
+ !invoke_pmd_refwrap<MemObj, Class, T>;
+
+// ΒΆ 1.7 says to just return f(t1, t2, ..., tn) in all other cases
+
+// Just internal forward declarations for SFINAE; cpp20::invoke is defined in
+// lib/stdcompat/functional.h
+template <typename MemFn, typename Class, typename T, typename... Args>
+constexpr auto invoke(MemFn Class::*f, T&& obj, Args&&... args)
+ -> std::enable_if_t<invoke_pmf_base<MemFn, Class, T>,
+ decltype((std::forward<T>(obj).*f)(std::forward<Args>(args)...))>;
+
+template <typename MemFn, typename Class, typename T, typename... Args>
+constexpr auto invoke(MemFn Class::*f, T&& obj, Args&&... args)
+ -> std::enable_if_t<invoke_pmf_refwrap<MemFn, Class, T>,
+ decltype((obj.get().*f)(std::forward<Args>(args)...))>;
+
+template <typename MemFn, typename Class, typename T, typename... Args>
+constexpr auto invoke(MemFn Class::*f, T&& obj, Args&&... args)
+ -> std::enable_if_t<invoke_pmf_other<MemFn, Class, T>,
+ decltype(((*std::forward<T>(obj)).*f)(std::forward<Args>(args)...))>;
+
+template <typename MemObj, typename Class, typename T>
+constexpr auto invoke(MemObj Class::*f, T&& obj)
+ -> std::enable_if_t<invoke_pmd_base<MemObj, Class, T>, decltype(std::forward<T>(obj).*f)>;
+
+template <typename MemObj, typename Class, typename T>
+constexpr auto invoke(MemObj Class::*f, T&& obj)
+ -> std::enable_if_t<invoke_pmd_refwrap<MemObj, Class, T>, decltype(obj.get().*f)>;
+
+template <typename MemObj, typename Class, typename T>
+constexpr auto invoke(MemObj Class::*f, T&& obj)
+ -> std::enable_if_t<invoke_pmd_other<MemObj, Class, T>, decltype((*std::forward<T>(obj)).*f)>;
+
+template <typename F, typename... Args>
+constexpr auto invoke(F&& f, Args&&... args)
+ -> decltype(std::forward<F>(f)(std::forward<Args>(args)...));
+
+template <typename R, typename F, typename... Args,
+ typename = std::enable_if_t<std::is_void<R>::value>>
+constexpr auto invoke_r(F&& f, Args&&... args)
+ -> decltype(static_cast<void>(::cpp17::internal::invoke(std::forward<F>(f),
+ std::forward<Args>(args)...)));
+
+template <typename R, typename F, typename... Args,
+ typename = std::enable_if_t<!std::is_void<R>::value>>
+constexpr auto invoke_r(F&& f, Args&&... args)
+ -> std::enable_if_t<std::is_convertible<decltype(::cpp17::internal::invoke(
+ std::forward<F>(f), std::forward<Args>(args)...)),
+ R>::value,
+ R>;
+
+template <typename R, typename F, typename... Args>
+constexpr auto is_valid_invoke(std::nullptr_t)
+ -> decltype(invoke_r<R>(std::declval<F>(), std::declval<Args>()...), std::true_type());
+
+template <typename R, typename F, typename... Args>
+constexpr std::false_type is_valid_invoke(...);
+
+template <bool Enable, typename F, typename... Args>
+struct invoke_result {};
+
+template <typename F, typename... Args>
+struct invoke_result<true, F, Args...> {
+ using type = decltype(::cpp17::internal::invoke(std::declval<F>(), std::declval<Args>()...));
+};
+
+} // namespace internal
+} // namespace cpp17
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_TYPE_TRAITS_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h
new file mode 100644
index 000000000..a5da381ae
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/internal/utility.h
@@ -0,0 +1,137 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_UTILITY_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_UTILITY_H_
+
+#include <cstddef>
+#include <utility>
+
+#include "../type_traits.h"
+
+namespace cpp17 {
+namespace internal {
+
+template <typename Tag>
+struct instantiate_templated_tag {
+ static constexpr const Tag storage{};
+};
+
+template <typename Tag>
+constexpr const Tag instantiate_templated_tag<Tag>::storage;
+
+template <typename T, typename ValueType, ValueType Value>
+struct inline_storage {
+ static constexpr const ValueType storage{Value};
+};
+
+template <typename T, typename ValueType, ValueType Value>
+constexpr const ValueType inline_storage<T, ValueType, Value>::storage;
+
+// Utility to return the first type in a parameter pack.
+template <typename... Ts>
+struct first;
+template <typename First, typename... Rest>
+struct first<First, Rest...> {
+ using type = First;
+};
+
+template <typename... Ts>
+using first_t = typename first<Ts...>::type;
+
+// Utility to count the occurences of type T in the parameter pack Ts.
+template <typename T, typename... Ts>
+struct occurences_of : std::integral_constant<std::size_t, 0> {};
+template <typename T, typename U>
+struct occurences_of<T, U> : std::integral_constant<std::size_t, std::is_same<T, U>::value> {};
+template <typename T, typename First, typename... Rest>
+struct occurences_of<T, First, Rest...>
+ : std::integral_constant<std::size_t,
+ occurences_of<T, First>::value + occurences_of<T, Rest...>::value> {};
+
+template <typename T, typename... Ts>
+constexpr std::size_t occurences_of_v = occurences_of<T, Ts...>::value;
+
+// Evaluates to truth-like when type T matches type U with cv-reference removed.
+template <typename T, typename U>
+using not_same_type = negation<std::is_same<T, ::cpp20::remove_cvref_t<U>>>;
+
+// Concept helper for constructors.
+template <typename... Conditions>
+using requires_conditions = std::enable_if_t<conjunction_v<Conditions...>, bool>;
+
+// Concept helper for assignment operators.
+template <typename Return, typename... Conditions>
+using assignment_requires_conditions =
+ std::enable_if_t<conjunction_v<Conditions...>, std::add_lvalue_reference_t<Return>>;
+
+// Evaluates to true when every element type of Ts is trivially destructible.
+template <typename... Ts>
+constexpr bool is_trivially_destructible_v = conjunction_v<std::is_trivially_destructible<Ts>...>;
+
+// Evaluates to true when every element type of Ts is trivially copyable.
+template <typename... Ts>
+constexpr bool is_trivially_copyable_v =
+ (conjunction_v<std::is_trivially_copy_assignable<Ts>...> &&
+ conjunction_v<std::is_trivially_copy_constructible<Ts>...>);
+
+// Evaluates to true when every element type of Ts is trivially movable.
+template <typename... Ts>
+constexpr bool is_trivially_movable_v =
+ (conjunction_v<std::is_trivially_move_assignable<Ts>...> &&
+ conjunction_v<std::is_trivially_move_constructible<Ts>...>);
+
+// Enable if relational operator is convertible to bool and the optional
+// conditions are true.
+template <typename Op, typename... Conditions>
+using enable_relop_t =
+ std::enable_if_t<(std::is_convertible<Op, bool>::value && conjunction_v<Conditions...>), bool>;
+
+// Returns true when T is a complete type or an unbounded array.
+template <typename T, std::size_t = sizeof(T)>
+constexpr bool is_complete_or_unbounded_array(::cpp20::type_identity<T>) {
+ return true;
+}
+template <typename Identity, typename T = typename Identity::type>
+constexpr bool is_complete_or_unbounded_array(Identity) {
+ return disjunction<std::is_reference<T>, std::is_function<T>, std::is_void<T>,
+ ::cpp20::is_unbounded_array<T>>::value;
+}
+
+// Using swap for ADL. This directive is contained within the cpp17::internal
+// namespace, which prevents leaking std::swap into user namespaces. Doing this
+// at namespace scope is necessary to lookup swap via ADL while preserving the
+// noexcept() specification of the resulting lookup.
+using std::swap;
+
+// Evaluates to true when T is swappable.
+template <typename T, typename = void>
+struct is_swappable : std::false_type {
+ static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+template <typename T>
+struct is_swappable<T, void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
+ : std::true_type {
+ static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+
+// Evaluates to true when T is nothrow swappable.
+template <typename T, typename = void>
+struct is_nothrow_swappable : std::false_type {
+ static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+template <typename T>
+struct is_nothrow_swappable<T, void_t<decltype(swap(std::declval<T&>(), std::declval<T&>()))>>
+ : std::integral_constant<bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))> {
+ static_assert(is_complete_or_unbounded_array(::cpp20::type_identity<T>{}),
+ "T must be a complete type or an unbounded array!");
+};
+
+} // namespace internal
+} // namespace cpp17
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_INTERNAL_UTILITY_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/memory.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/memory.h
new file mode 100644
index 000000000..2dc3198a4
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/memory.h
@@ -0,0 +1,66 @@
+// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_MEMORY_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_MEMORY_H_
+
+#include <memory>
+
+#include "version.h"
+
+namespace cpp17 {
+
+#if defined(__cpp_lib_addressof_constexpr) && __cpp_lib_addressof_constexpr >= 201603L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::addressof;
+
+#else // Provide constexpr polyfill for addressof.
+
+template <typename T>
+constexpr T* addressof(T& arg) noexcept {
+ return __builtin_addressof(arg);
+}
+
+template <typename T>
+const T* addressof(const T&&) = delete;
+
+#endif // __cpp_lib_addressof_constexpr >= 201603L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp17
+
+namespace cpp20 {
+
+#if defined(__cpp_lib_to_address) && __cpp_lib_to_address >= 201711L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::to_address;
+
+#else // Provide to_address polyfill.
+
+template <typename T>
+constexpr T* to_address(T* pointer) noexcept {
+ static_assert(!std::is_function<T>::value, "Cannot pass function pointers to std::to_address()");
+ return pointer;
+}
+
+// TODO(fxbug.dev/70523): This std::pointer_traits stuff is only to be bug-compatible with the
+// standard library implementations; switch back to auto when the linked bug is resolved.
+template <typename T>
+constexpr typename std::pointer_traits<T>::element_type* to_address(const T& pointer) noexcept {
+ static_assert(
+ std::is_same<decltype(pointer.operator->()),
+ typename std::pointer_traits<T>::element_type*>::value,
+ "For compatibility with libc++ and libstdc++, operator->() must return "
+ "typename std::pointer_traits<T>::element_type*. 'Chaining' operator->() in "
+ "cpp20::to_address() will not be permitted until https://fxbug.dev/70523 is resolved.");
+
+ return to_address(pointer.operator->());
+}
+
+#endif // __cpp_lib_to_address >= 201711L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp20
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_MEMORY_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/optional.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/optional.h
new file mode 100644
index 000000000..bc6a421a0
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/optional.h
@@ -0,0 +1,475 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_OPTIONAL_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_OPTIONAL_H_
+
+#include "utility.h"
+#include "version.h"
+
+#if defined(__cpp_lib_optional) && __cpp_lib_optional >= 201606L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#include <optional>
+
+namespace cpp17 {
+
+using std::bad_optional_access;
+using std::make_optional;
+using std::nullopt;
+using std::nullopt_t;
+using std::optional;
+
+} // namespace cpp17
+
+#else // Provide std::optional and std::nullopt_t polyfill.
+
+#include <cstdlib>
+#include <exception>
+#include <new>
+
+#include "internal/constructors.h"
+#include "internal/exception.h"
+#include "internal/storage.h"
+#include "internal/utility.h"
+#include "type_traits.h"
+
+namespace cpp17 {
+
+// A sentinel value for indicating that it contains no value.
+struct nullopt_t {
+ explicit constexpr nullopt_t(int) {}
+};
+static constexpr nullopt_t nullopt{0};
+
+// Exception type to report bad accesses to optional.
+class bad_optional_access : public std::exception {
+ public:
+ bad_optional_access() noexcept {}
+
+ const char* what() const noexcept override { return reason_; }
+
+ private:
+ template <typename T>
+ friend class optional;
+
+ bad_optional_access(const char* reason) noexcept : reason_{reason} {}
+
+ // String describing the reason for the bad access. Must point to a string
+ // with static storage duration.
+ const char* reason_;
+
+ template <typename T,
+ typename std::enable_if<std::is_base_of<std::exception, T>::value, bool>::type>
+ friend constexpr void cpp17::internal::throw_or_abort(const char*);
+};
+
+// A reasonably complete implementation of std::optional compatible with C++14.
+template <typename T>
+class optional : private ::cpp17::internal::modulate_copy_and_move<T> {
+ private:
+ // Helper types and values for SFINAE and noexcept rules.
+ static constexpr bool nothrow_move_constructible = std::is_nothrow_move_constructible<T>::value;
+
+ static constexpr bool nothrow_swappable = std::is_nothrow_move_constructible<T>::value &&
+ ::cpp17::internal::is_nothrow_swappable<T>::value;
+
+ static constexpr auto trivial_init_v = ::cpp17::internal::trivial_init_v;
+ static constexpr auto maybe_init_v = ::cpp17::internal::maybe_init_v;
+ using type_tag = ::cpp17::internal::type_tag<T>;
+
+ template <typename U, typename V>
+ using converts_from_optional = disjunction<
+ std::is_constructible<U, const optional<V>&>, std::is_constructible<U, optional<V>&>,
+ std::is_constructible<U, const optional<V>&&>, std::is_constructible<U, optional<V>&&>,
+ std::is_convertible<const optional<V>&, U>, std::is_convertible<optional<V>&, U>,
+ std::is_convertible<const optional<V>&&, U>, std::is_convertible<optional<V>&&, U>>;
+
+ template <typename U, typename V>
+ using assigns_from_optional =
+ disjunction<std::is_assignable<U&, const optional<V>&>, std::is_assignable<U&, optional<V>&>,
+ std::is_assignable<U&, const optional<V>&&>,
+ std::is_assignable<U&, optional<V>&&>>;
+
+ template <typename U>
+ using not_self_type = ::cpp17::internal::not_same_type<optional, U>;
+
+ template <typename U>
+ using not_in_place = ::cpp17::internal::not_same_type<in_place_t, U>;
+
+ template <typename... Conditions>
+ using requires_conditions = ::cpp17::internal::requires_conditions<Conditions...>;
+
+ template <typename... Conditions>
+ using assignment_requires_conditions =
+ ::cpp17::internal::assignment_requires_conditions<optional&, Conditions...>;
+
+ template <typename... Args>
+ using emplace_constructible = std::enable_if_t<std::is_constructible<T, Args...>::value, T&>;
+
+ public:
+ using value_type = T;
+
+ // Default constructors.
+
+ constexpr optional() = default;
+
+ constexpr optional(nullopt_t) noexcept {}
+
+ // Copy/move constructors and assignment operators.
+
+ constexpr optional(const optional&) = default;
+ constexpr optional& operator=(const optional&) = default;
+
+ constexpr optional(optional&&) = default;
+ constexpr optional& operator=(optional&&) = default;
+
+ // Converting constructors.
+
+ template <typename U = T,
+ requires_conditions<not_self_type<U>, not_in_place<U>, std::is_constructible<T, U&&>,
+ std::is_convertible<U&&, T>> = true>
+ constexpr optional(U&& value) : storage_(type_tag{}, std::forward<U>(value)) {}
+
+ template <typename U = T,
+ requires_conditions<not_self_type<U>, not_in_place<U>, std::is_constructible<T, U&&>,
+ negation<std::is_convertible<U&&, T>>> = false>
+ explicit constexpr optional(U&& value) : storage_{type_tag{}, std::forward<U>(value)} {}
+
+ template <typename U,
+ requires_conditions<negation<std::is_same<T, U>>, std::is_constructible<T, const U&>,
+ std::is_convertible<const U&, T>,
+ negation<converts_from_optional<T, U>>> = true>
+ constexpr optional(const optional<U>& other) : storage_{maybe_init_v, other.storage_} {}
+
+ template <typename U,
+ requires_conditions<negation<std::is_same<T, U>>, std::is_constructible<T, const U&>,
+ negation<std::is_convertible<const U&, T>>,
+ negation<converts_from_optional<T, U>>> = false>
+ explicit constexpr optional(const optional<U>& other) : storage_{maybe_init_v, other.storage_} {}
+
+ template <typename U,
+ requires_conditions<negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+ std::is_convertible<U&&, T>,
+ negation<converts_from_optional<T, U>>> = true>
+ constexpr optional(optional<U>&& other) : storage_{maybe_init_v, std::move(other.storage_)} {}
+
+ template <typename U,
+ requires_conditions<negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+ negation<std::is_convertible<U&&, T>>,
+ negation<converts_from_optional<T, U>>> = false>
+ explicit constexpr optional(optional<U>&& other)
+ : storage_{maybe_init_v, std::move(other.storage_)} {}
+
+ template <typename... Args, requires_conditions<std::is_constructible<T, Args&&...>> = false>
+ explicit constexpr optional(in_place_t, Args&&... args)
+ : storage_(type_tag{}, std::forward<Args>(args)...) {}
+
+ template <
+ typename U, typename... Args,
+ requires_conditions<std::is_constructible<T, std::initializer_list<U>&, Args&&...>> = false>
+ explicit constexpr optional(in_place_t, std::initializer_list<U> init_list, Args&&... args)
+ : storage_(type_tag{}, init_list, std::forward<Args>(args)...) {}
+
+ // Destructor.
+
+ ~optional() = default;
+
+ // Checked accessors.
+
+ constexpr T& value() & {
+ if (has_value()) {
+ return storage_.get(type_tag{});
+ }
+ internal::throw_or_abort<bad_optional_access>("Accessed value of empty optional!");
+ }
+ constexpr const T& value() const& {
+ if (has_value()) {
+ return storage_.get(type_tag{});
+ }
+ internal::throw_or_abort<bad_optional_access>("Accessed value of empty optional!");
+ }
+ constexpr T&& value() && {
+ if (has_value()) {
+ return std::move(storage_.get(type_tag{}));
+ }
+ internal::throw_or_abort<bad_optional_access>("Accessed value of empty optional!");
+ }
+ constexpr const T&& value() const&& {
+ if (has_value()) {
+ return std::move(storage_.get(type_tag{}));
+ }
+ internal::throw_or_abort<bad_optional_access>("Accessed value of empty optional!");
+ }
+
+ template <typename U>
+ constexpr T value_or(U&& default_value) const& {
+ static_assert(std::is_copy_constructible<T>::value,
+ "value_or() requires copy-constructible value_type!");
+ static_assert(std::is_convertible<U&&, T>::value,
+ "Default value must be convertible to value_type!");
+
+ return has_value() ? storage_.get(type_tag{}) : static_cast<T>(std::forward<U>(default_value));
+ }
+ template <typename U>
+ constexpr T value_or(U&& default_value) && {
+ static_assert(std::is_move_constructible<T>::value,
+ "value_or() requires move-constructible value_type!");
+ static_assert(std::is_convertible<U&&, T>::value,
+ "Default value must be convertible to value_type!");
+
+ return has_value() ? std::move(storage_.get(type_tag{}))
+ : static_cast<T>(std::forward<U>(default_value));
+ }
+
+ // Unchecked accessors.
+
+ constexpr T* operator->() { return std::addressof(storage_.get(type_tag{})); }
+ constexpr const T* operator->() const { return std::addressof(storage_.get(type_tag{})); }
+
+ constexpr T& operator*() { return storage_.get(type_tag{}); }
+ constexpr const T& operator*() const { return storage_.get(type_tag{}); }
+
+ // Availability accessors/operators.
+
+ constexpr bool has_value() const { return !storage_.is_empty(); }
+ constexpr explicit operator bool() const { return has_value(); }
+
+ // Assignment operators.
+
+ template <typename U>
+ constexpr assignment_requires_conditions<
+ not_self_type<U>, negation<conjunction<std::is_scalar<T>, std::is_same<T, std::decay_t<U>>>>,
+ std::is_constructible<T, U>, std::is_assignable<T&, U>>
+ operator=(U&& value) {
+ if (has_value()) {
+ storage_.get(type_tag{}) = std::forward<U>(value);
+ } else {
+ storage_.construct(type_tag{}, std::forward<U>(value));
+ }
+ return *this;
+ }
+
+ template <typename U>
+ constexpr assignment_requires_conditions<
+ negation<std::is_same<T, U>>, std::is_constructible<T, const U&>, std::is_assignable<T&, U>,
+ negation<converts_from_optional<T, U>>, negation<assigns_from_optional<T, U>>>
+ operator=(const optional<U>& other) {
+ storage_.assign(other.storage_);
+ return *this;
+ }
+
+ template <typename U>
+ constexpr assignment_requires_conditions<
+ negation<std::is_same<T, U>>, std::is_constructible<T, U>, std::is_assignable<T&, U>,
+ negation<converts_from_optional<T, U>>, negation<assigns_from_optional<T, U>>>
+ operator=(optional<U>&& other) {
+ storage_.assign(std::move(other.storage_));
+ return *this;
+ }
+
+ constexpr optional& operator=(nullopt_t) {
+ storage_.reset();
+ return *this;
+ }
+
+ // Swap.
+
+ constexpr void swap(optional& other) noexcept(nothrow_swappable) {
+ storage_.swap(other.storage_);
+ }
+
+ // Emplacement.
+
+ template <typename... Args>
+ constexpr emplace_constructible<Args&&...> emplace(Args&&... args) {
+ storage_.reset();
+ storage_.construct(type_tag{}, std::forward<Args>(args)...);
+ return storage_.get(type_tag{});
+ }
+
+ template <typename U, typename... Args>
+ constexpr emplace_constructible<std::initializer_list<U>&, Args&&...> emplace(
+ std::initializer_list<U> init_list, Args&&... args) {
+ storage_.reset();
+ storage_.construct(type_tag{}, init_list, std::forward<Args>(args)...);
+ return storage_.get(type_tag{});
+ }
+
+ // Reset.
+
+ void reset() noexcept { storage_.reset(); }
+
+ private:
+ ::cpp17::internal::storage_type<T> storage_;
+};
+
+// Swap.
+template <typename T>
+inline std::enable_if_t<(std::is_move_constructible<T>::value &&
+ ::cpp17::internal::is_swappable<T>::value)>
+swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
+ a.swap(b);
+}
+template <typename T>
+inline std::enable_if_t<(!std::is_move_constructible<T>::value &&
+ ::cpp17::internal::is_swappable<T>::value)>
+swap(optional<T>& a, optional<T>& b) = delete;
+
+// Make optional.
+template <typename T>
+constexpr optional<std::decay_t<T>> make_optional(T&& value) {
+ return optional<std::decay_t<T>>{std::forward<T>(value)};
+}
+template <typename T, typename... Args>
+constexpr optional<T> make_optional(Args&&... args) {
+ return optional<T>{in_place, std::forward<Args>(args)...};
+}
+template <typename T, typename U, typename... Args>
+constexpr optional<T> make_optional(std::initializer_list<U> init_list, Args&&... args) {
+ return optional<T>{in_place, init_list, std::forward<Args>(args)...};
+}
+
+// Empty.
+template <typename T>
+constexpr bool operator==(const optional<T>& lhs, nullopt_t) {
+ return !lhs.has_value();
+}
+template <typename T>
+constexpr bool operator!=(const optional<T>& lhs, nullopt_t) {
+ return lhs.has_value();
+}
+
+template <typename T>
+constexpr bool operator==(nullopt_t, const optional<T>& rhs) {
+ return !rhs.has_value();
+}
+template <typename T>
+constexpr bool operator!=(nullopt_t, const optional<T>& rhs) {
+ return rhs.has_value();
+}
+
+// Equal/not equal.
+template <
+ typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() == std::declval<U>())> = true>
+constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
+ return (lhs.has_value() == rhs.has_value()) && (!lhs.has_value() || *lhs == *rhs);
+}
+template <
+ typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() != std::declval<U>())> = true>
+constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs) {
+ return (lhs.has_value() != rhs.has_value()) || (lhs.has_value() && *lhs != *rhs);
+}
+
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() == std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, U>> = true>
+constexpr bool operator==(const optional<T>& lhs, const U& rhs) {
+ return lhs.has_value() && *lhs == rhs;
+}
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() != std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, U>> = true>
+constexpr bool operator!=(const optional<T>& lhs, const U& rhs) {
+ return !lhs.has_value() || *lhs != rhs;
+}
+
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() == std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, T>> = true>
+constexpr bool operator==(const T& lhs, const optional<U>& rhs) {
+ return rhs.has_value() && lhs == *rhs;
+}
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() != std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, T>> = true>
+constexpr bool operator!=(const T& lhs, const optional<U>& rhs) {
+ return !rhs.has_value() || lhs != *rhs;
+}
+
+// Less than/greater than.
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() < std::declval<U>())> = true>
+constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs) {
+ return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs);
+}
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() > std::declval<U>())> = true>
+constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs) {
+ return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs);
+}
+
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() < std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, U>> = true>
+constexpr bool operator<(const optional<T>& lhs, const U& rhs) {
+ return !lhs.has_value() || *lhs < rhs;
+}
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() > std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, U>> = true>
+constexpr bool operator>(const optional<T>& lhs, const U& rhs) {
+ return lhs.has_value() && *lhs > rhs;
+}
+
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() < std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, T>> = true>
+constexpr bool operator<(const T& lhs, const optional<U>& rhs) {
+ return rhs.has_value() && lhs < *rhs;
+}
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() > std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, T>> = true>
+constexpr bool operator>(const T& lhs, const optional<U>& rhs) {
+ return !rhs.has_value() || lhs > *rhs;
+}
+
+// Less than or equal/greater than or equal.
+template <
+ typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() <= std::declval<U>())> = true>
+constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs) {
+ return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs);
+}
+template <
+ typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() >= std::declval<U>())> = true>
+constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs) {
+ return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs);
+}
+
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() <= std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, U>> = true>
+constexpr bool operator<=(const optional<T>& lhs, const U& rhs) {
+ return !lhs.has_value() || *lhs <= rhs;
+}
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() >= std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, U>> = true>
+constexpr bool operator>=(const optional<T>& lhs, const U& rhs) {
+ return lhs.has_value() && *lhs >= rhs;
+}
+
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() <= std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, T>> = true>
+constexpr bool operator<=(const T& lhs, const optional<U>& rhs) {
+ return rhs.has_value() && lhs <= *rhs;
+}
+template <typename T, typename U,
+ ::cpp17::internal::enable_relop_t<decltype(std::declval<T>() >= std::declval<U>()),
+ ::cpp17::internal::not_same_type<nullopt_t, T>> = true>
+constexpr bool operator>=(const T& lhs, const optional<U>& rhs) {
+ return !rhs.has_value() || lhs >= *rhs;
+}
+
+} // namespace cpp17
+
+#endif
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_OPTIONAL_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/type_traits.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/type_traits.h
new file mode 100644
index 000000000..8f0d80ede
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/type_traits.h
@@ -0,0 +1,509 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_TYPE_TRAITS_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_TYPE_TRAITS_H_
+
+#include <cstddef>
+#include <tuple>
+#include <type_traits>
+
+#include "internal/type_traits.h"
+#include "version.h"
+
+namespace cpp17 {
+
+#if defined(__cpp_lib_void_t) && __cpp_lib_void_t >= 201411L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+using std::void_t;
+#else // Provide std::void_t polyfill.
+template <typename... T>
+using void_t = void;
+#endif // __cpp_lib_void_t >= 201411L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_logical_traits) && __cpp_lib_logical_traits >= 201510L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::conjunction;
+using std::conjunction_v;
+using std::disjunction;
+using std::disjunction_v;
+using std::negation;
+using std::negation_v;
+
+#else // Provide polyfills for std::{negation, conjunction, disjunction} and the *_v helpers.
+
+template <typename... Ts>
+struct conjunction : std::true_type {};
+template <typename T>
+struct conjunction<T> : T {};
+template <typename First, typename... Rest>
+struct conjunction<First, Rest...>
+ : std::conditional_t<bool(First::value), conjunction<Rest...>, First> {};
+
+template <typename... Ts>
+static constexpr bool conjunction_v = conjunction<Ts...>::value;
+
+template <typename... Ts>
+struct disjunction : std::false_type {};
+template <typename T>
+struct disjunction<T> : T {};
+template <typename First, typename... Rest>
+struct disjunction<First, Rest...>
+ : std::conditional_t<bool(First::value), First, disjunction<Rest...>> {};
+
+template <typename... Ts>
+static constexpr bool disjunction_v = disjunction<Ts...>::value;
+
+// Utility type that negates its truth-like parameter type.
+template <typename T>
+struct negation : std::integral_constant<bool, !bool(T::value)> {};
+
+template <typename T>
+static constexpr bool negation_v = negation<T>::value;
+
+#endif // __cpp_lib_logical_traits >= 201510L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_bool_constant) && __cpp_lib_bool_constant >= 201505L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::bool_constant;
+
+#else // Provide polyfill for std::bool_constant
+
+template <bool B>
+using bool_constant = std::integral_constant<bool, B>;
+
+#endif // __cpp_lib_bool_constant >= 201505L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_type_trait_variable_templates) && \
+ __cpp_lib_type_trait_variable_templates >= 201510L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::is_array_v;
+using std::is_class_v;
+using std::is_enum_v;
+using std::is_floating_point_v;
+using std::is_function_v;
+using std::is_integral_v;
+using std::is_lvalue_reference_v;
+using std::is_member_function_pointer_v;
+using std::is_member_object_pointer_v;
+using std::is_null_pointer_v;
+using std::is_pointer_v;
+using std::is_rvalue_reference_v;
+using std::is_union_v;
+using std::is_void_v;
+
+using std::is_arithmetic_v;
+using std::is_compound_v;
+using std::is_fundamental_v;
+using std::is_member_pointer_v;
+using std::is_object_v;
+using std::is_reference_v;
+using std::is_scalar_v;
+
+using std::is_abstract_v;
+using std::is_const_v;
+using std::is_empty_v;
+using std::is_final_v;
+using std::is_pod_v;
+using std::is_polymorphic_v;
+using std::is_signed_v;
+using std::is_standard_layout_v;
+using std::is_trivial_v;
+using std::is_trivially_copyable_v;
+using std::is_unsigned_v;
+using std::is_volatile_v;
+
+using std::is_constructible_v;
+using std::is_nothrow_constructible_v;
+using std::is_trivially_constructible_v;
+
+using std::is_default_constructible_v;
+using std::is_nothrow_default_constructible_v;
+using std::is_trivially_default_constructible_v;
+
+using std::is_copy_constructible_v;
+using std::is_nothrow_copy_constructible_v;
+using std::is_trivially_copy_constructible_v;
+
+using std::is_move_constructible_v;
+using std::is_nothrow_move_constructible_v;
+using std::is_trivially_move_constructible_v;
+
+using std::is_assignable_v;
+using std::is_nothrow_assignable_v;
+using std::is_trivially_assignable_v;
+
+using std::is_copy_assignable_v;
+using std::is_nothrow_copy_assignable_v;
+using std::is_trivially_copy_assignable_v;
+
+using std::is_move_assignable_v;
+using std::is_nothrow_move_assignable_v;
+using std::is_trivially_move_assignable_v;
+
+using std::is_destructible_v;
+using std::is_nothrow_destructible_v;
+using std::is_trivially_destructible_v;
+
+using std::has_virtual_destructor_v;
+
+using std::alignment_of_v;
+using std::extent_v;
+using std::rank_v;
+
+using std::is_base_of_v;
+using std::is_convertible_v;
+using std::is_same_v;
+
+#else // Provide polyfills for the bulk of the *_v helpers
+
+template <typename T>
+static constexpr bool is_void_v = std::is_void<T>::value;
+template <typename T>
+static constexpr bool is_null_pointer_v = std::is_null_pointer<T>::value;
+template <typename T>
+static constexpr bool is_integral_v = std::is_integral<T>::value;
+template <typename T>
+static constexpr bool is_floating_point_v = std::is_floating_point<T>::value;
+template <typename T>
+static constexpr bool is_array_v = std::is_array<T>::value;
+template <typename T>
+static constexpr bool is_enum_v = std::is_enum<T>::value;
+template <typename T>
+static constexpr bool is_union_v = std::is_union<T>::value;
+template <typename T>
+static constexpr bool is_class_v = std::is_class<T>::value;
+template <typename T>
+static constexpr bool is_function_v = std::is_function<T>::value;
+template <typename T>
+static constexpr bool is_pointer_v = std::is_pointer<T>::value;
+template <typename T>
+static constexpr bool is_lvalue_reference_v = std::is_lvalue_reference<T>::value;
+template <typename T>
+static constexpr bool is_rvalue_reference_v = std::is_rvalue_reference<T>::value;
+template <typename T>
+static constexpr bool is_member_object_pointer_v = std::is_member_object_pointer<T>::value;
+template <typename T>
+static constexpr bool is_member_function_pointer_v = std::is_member_function_pointer<T>::value;
+
+template <typename T>
+static constexpr bool is_fundamental_v = std::is_fundamental<T>::value;
+template <typename T>
+static constexpr bool is_arithmetic_v = std::is_arithmetic<T>::value;
+template <typename T>
+static constexpr bool is_scalar_v = std::is_scalar<T>::value;
+template <typename T>
+static constexpr bool is_object_v = std::is_object<T>::value;
+template <typename T>
+static constexpr bool is_compound_v = std::is_compound<T>::value;
+template <typename T>
+static constexpr bool is_reference_v = std::is_reference<T>::value;
+template <typename T>
+static constexpr bool is_member_pointer_v = std::is_member_pointer<T>::value;
+
+template <typename T>
+static constexpr bool is_const_v = std::is_const<T>::value;
+template <typename T>
+static constexpr bool is_volatile_v = std::is_volatile<T>::value;
+template <typename T>
+static constexpr bool is_trivial_v = std::is_trivial<T>::value;
+template <typename T>
+static constexpr bool is_trivially_copyable_v = std::is_trivially_copyable<T>::value;
+template <typename T>
+static constexpr bool is_standard_layout_v = std::is_standard_layout<T>::value;
+template <typename T>
+[[deprecated]] static constexpr bool is_pod_v = std::is_pod<T>::value;
+template <typename T>
+static constexpr bool is_empty_v = std::is_empty<T>::value;
+template <typename T>
+static constexpr bool is_polymorphic_v = std::is_polymorphic<T>::value;
+template <typename T>
+static constexpr bool is_abstract_v = std::is_abstract<T>::value;
+template <typename T>
+static constexpr bool is_final_v = std::is_final<T>::value;
+template <typename T>
+static constexpr bool is_signed_v = std::is_signed<T>::value;
+template <typename T>
+static constexpr bool is_unsigned_v = std::is_unsigned<T>::value;
+
+template <typename T, typename... Args>
+static constexpr bool is_constructible_v = std::is_constructible<T, Args...>::value;
+template <typename T, typename... Args>
+static constexpr bool is_trivially_constructible_v =
+ std::is_trivially_constructible<T, Args...>::value;
+template <typename T, typename... Args>
+static constexpr bool is_nothrow_constructible_v = std::is_nothrow_constructible<T, Args...>::value;
+
+template <typename T>
+static constexpr bool is_default_constructible_v = std::is_default_constructible<T>::value;
+template <typename T>
+static constexpr bool is_trivially_default_constructible_v =
+ std::is_trivially_default_constructible<T>::value;
+template <typename T>
+static constexpr bool is_nothrow_default_constructible_v =
+ std::is_nothrow_default_constructible<T>::value;
+
+template <typename T>
+static constexpr bool is_copy_constructible_v = std::is_copy_constructible<T>::value;
+template <typename T>
+static constexpr bool is_trivially_copy_constructible_v =
+ std::is_trivially_copy_constructible<T>::value;
+template <typename T>
+static constexpr bool is_nothrow_copy_constructible_v =
+ std::is_nothrow_copy_constructible<T>::value;
+
+template <typename T>
+static constexpr bool is_move_constructible_v = std::is_move_constructible<T>::value;
+template <typename T>
+static constexpr bool is_trivially_move_constructible_v =
+ std::is_trivially_move_constructible<T>::value;
+template <typename T>
+static constexpr bool is_nothrow_move_constructible_v =
+ std::is_nothrow_move_constructible<T>::value;
+
+template <typename T, typename U>
+static constexpr bool is_assignable_v = std::is_assignable<T, U>::value;
+template <typename T, typename U>
+static constexpr bool is_trivially_assignable_v = std::is_trivially_assignable<T, U>::value;
+template <typename T, typename U>
+static constexpr bool is_nothrow_assignable_v = std::is_nothrow_assignable<T, U>::value;
+
+template <typename T>
+static constexpr bool is_copy_assignable_v = std::is_copy_assignable<T>::value;
+template <typename T>
+static constexpr bool is_trivially_copy_assignable_v = std::is_trivially_copy_assignable<T>::value;
+template <typename T>
+static constexpr bool is_nothrow_copy_assignable_v = std::is_nothrow_copy_assignable<T>::value;
+
+template <typename T>
+static constexpr bool is_move_assignable_v = std::is_move_assignable<T>::value;
+template <typename T>
+static constexpr bool is_trivially_move_assignable_v = std::is_trivially_move_assignable<T>::value;
+template <typename T>
+static constexpr bool is_nothrow_move_assignable_v = std::is_nothrow_move_assignable<T>::value;
+
+template <typename T>
+static constexpr bool is_destructible_v = std::is_destructible<T>::value;
+template <typename T>
+static constexpr bool is_trivially_destructible_v = std::is_trivially_destructible<T>::value;
+template <typename T>
+static constexpr bool is_nothrow_destructible_v = std::is_nothrow_destructible<T>::value;
+
+template <typename T>
+static constexpr bool has_virtual_destructor_v = std::has_virtual_destructor<T>::value;
+
+template <typename T>
+static constexpr bool alignment_of_v = std::alignment_of<T>::value;
+template <typename T>
+static constexpr bool rank_v = std::rank<T>::value;
+template <typename T, unsigned N = 0>
+static constexpr bool extent_v = std::extent<T, N>::value;
+
+template <typename T, typename U>
+static constexpr bool is_same_v = std::is_same<T, U>::value;
+template <typename T, typename U>
+static constexpr bool is_base_of_v = std::is_base_of<T, U>::value;
+template <typename T, typename U>
+static constexpr bool is_convertible_v = std::is_convertible<T, U>::value;
+
+#endif // __cpp_lib_type_trait_variable_templates >= 201510L &&
+ // !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_is_aggregate) && __cpp_lib_is_aggregate >= 201703L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::is_aggregate;
+using std::is_aggregate_v;
+
+#else // Provide std::is_aggregate polyfill
+
+template <typename T>
+struct is_aggregate : bool_constant<__is_aggregate(T)> {};
+
+template <typename T>
+static constexpr bool is_aggregate_v = is_aggregate<T>::value;
+
+#endif // __cpp_lib_is_aggregate >= 201703L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::is_invocable;
+using std::is_invocable_r;
+using std::is_nothrow_invocable;
+using std::is_nothrow_invocable_r;
+
+using std::is_invocable_r_v;
+using std::is_invocable_v;
+using std::is_nothrow_invocable_r_v;
+using std::is_nothrow_invocable_v;
+
+using std::invoke_result;
+using std::invoke_result_t;
+
+#else
+
+template <typename R, typename F, typename... Args>
+struct is_invocable_r : decltype(::cpp17::internal::is_valid_invoke<R, F, Args...>(nullptr)) {};
+
+template <typename R, typename F, typename... Args>
+static constexpr bool is_invocable_r_v = is_invocable_r<R, F, Args...>::value;
+
+// INVOKE() is a subexpression of INVOKE<R>()
+// INVOKE<void>(f, t1, t2, ..., tn) results in a call to
+// static_cast<void>(INVOKE(f, t1, t2, ..., tn)) per [func.require] ΒΆ 2
+template <typename F, typename... Args>
+struct is_invocable : is_invocable_r<void, F, Args...> {};
+
+template <typename F, typename... Args>
+static constexpr bool is_invocable_v = is_invocable<F, Args...>::value;
+
+template <typename F, typename... Args>
+struct is_nothrow_invocable : bool_constant<is_invocable_v<F, Args...> &&
+ noexcept(::cpp17::internal::invoke(
+ std::declval<F>(), std::declval<Args>()...))> {};
+
+template <typename F, typename... Args>
+static constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<F, Args...>::value;
+
+template <typename R, typename F, typename... Args>
+struct is_nothrow_invocable_r : bool_constant<is_invocable_r_v<R, F, Args...> &&
+ noexcept(::cpp17::internal::invoke_r<R>(
+ std::declval<F>(), std::declval<Args>()...))> {};
+
+template <typename R, typename F, typename... Args>
+static constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, F, Args...>::value;
+
+template <typename F, typename... Args>
+struct invoke_result : ::cpp17::internal::invoke_result<is_invocable_v<F, Args...>, F, Args...> {};
+
+template <typename F, typename... Args>
+using invoke_result_t = typename invoke_result<F, Args...>::type;
+
+#endif // __cpp_lib_is_invocable >= 201703L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp17
+
+namespace cpp20 {
+
+#if defined(__cpp_lib_bounded_array_traits) && __cpp_lib_bounded_array_traits >= 201902L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::is_bounded_array;
+using std::is_bounded_array_v;
+
+using std::is_unbounded_array;
+using std::is_unbounded_array_v;
+
+#else // Provide polyfills for std::is_{,un}bounded_array{,_v}
+
+template <typename T>
+struct is_bounded_array : std::false_type {};
+template <typename T, std::size_t N>
+struct is_bounded_array<T[N]> : std::true_type {};
+
+template <typename T>
+static constexpr bool is_bounded_array_v = is_bounded_array<T>::value;
+
+template <typename T>
+struct is_unbounded_array : std::false_type {};
+template <typename T>
+struct is_unbounded_array<T[]> : std::true_type {};
+
+template <typename T>
+static constexpr bool is_unbounded_array_v = is_unbounded_array<T>::value;
+
+#endif // __cpp_lib_bounded_array_traits >= 201902L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::remove_cvref;
+using std::remove_cvref_t;
+
+#else // Provide polyfill for std::remove_cvref{,_t}
+
+template <typename T>
+struct remove_cvref {
+ using type = std::remove_cv_t<std::remove_reference_t<T>>;
+};
+
+template <typename T>
+using remove_cvref_t = typename remove_cvref<T>::type;
+
+#endif // __cpp_lib_remove_cvref >= 201711L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_type_identity) && __cpp_lib_type_identity >= 201806L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::type_identity;
+using std::type_identity_t;
+
+#else // Provide polyfill for std::type_identity{,_t}
+
+template <typename T>
+struct type_identity {
+ using type = T;
+};
+
+template <typename T>
+using type_identity_t = typename type_identity<T>::type;
+
+#endif // __cpp_lib_type_identity >= 201806L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#define LIB_STDCOMPAT_CONSTEVAL_SUPPORT 1
+using std::is_constant_evaluated;
+
+#else // Provide polyfill for std::is_constant_evaluated
+
+#ifdef __has_builtin
+#if __has_builtin(__builtin_is_constant_evaluated)
+
+#define LIB_STDCOMPAT_CONSTEVAL_SUPPORT 1
+inline constexpr bool is_constant_evaluated() noexcept { return __builtin_is_constant_evaluated(); }
+
+#endif // __has_builtin(__builtin_is_constant_evaluated)
+#endif // __has_builtin
+
+#ifndef LIB_STDCOMPAT_CONSTEVAL_SUPPORT
+
+#define LIB_STDCOMPAT_CONSTEVAL_SUPPORT 0
+inline constexpr bool is_constant_evaluated() noexcept { return false; }
+
+#endif // LIB_STDCOMPAT_CONSTEVAL_SUPPORT
+
+#endif // __cpp_lib_is_constant_evaluated >= 201811L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp20
+
+namespace cpp23 {
+
+#if defined(__cpp_lib_is_scoped_enum) && __cpp_lib_is_scoped_enum >= 202011L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::is_scoped_enum;
+using std::is_scoped_enum_v;
+
+#else // Provide polyfill for std::is_scoped_enum{,_v}
+
+template <typename T, typename = void>
+struct is_scoped_enum : std::false_type {};
+
+template <typename T>
+struct is_scoped_enum<T, std::enable_if_t<cpp17::is_enum_v<T>>>
+ : cpp17::bool_constant<!cpp17::is_convertible_v<T, std::underlying_type_t<T>>> {};
+
+template <typename T>
+static constexpr bool is_scoped_enum_v = is_scoped_enum<T>::value;
+
+#endif // __cpp_lib_is_scoped_enum >= 202011L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp23
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_TYPE_TRAITS_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/utility.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/utility.h
new file mode 100644
index 000000000..fe0993d47
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/utility.h
@@ -0,0 +1,118 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_UTILITY_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_UTILITY_H_
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+#include "internal/utility.h"
+#include "version.h"
+
+namespace cpp17 {
+// Use alias for cpp17 and above.
+#if __cplusplus >= 201411L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::in_place;
+using std::in_place_t;
+
+using std::in_place_index;
+using std::in_place_index_t;
+
+using std::in_place_type;
+using std::in_place_type_t;
+
+#else // Provide provide polyfills for |in_place*| types and variables.
+
+// Tag for requesting in-place initialization.
+struct in_place_t {
+ explicit constexpr in_place_t() = default;
+};
+
+// Tag for requesting in-place initialization by type.
+template <typename T>
+struct in_place_type_t {
+ explicit constexpr in_place_type_t() = default;
+};
+
+// Tag for requesting in-place initialization by index.
+template <std::size_t Index>
+struct in_place_index_t final {
+ explicit constexpr in_place_index_t() = default;
+};
+
+// Use inline variables if available.
+#if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+constexpr in_place_t in_place{};
+
+template <typename T>
+constexpr in_place_type_t<T> in_place_type{};
+
+template <std::size_t Index>
+constexpr in_place_index_t<Index> in_place_index{};
+
+#else // Provide polyfill reference to provided variable storage.
+
+static constexpr const in_place_t& in_place =
+ internal::instantiate_templated_tag<in_place_t>::storage;
+
+template <typename T>
+static constexpr const in_place_type_t<T>& in_place_type =
+ internal::instantiate_templated_tag<in_place_type_t<T>>::storage;
+
+template <std::size_t Index>
+static constexpr const in_place_index_t<Index>& in_place_index =
+ internal::instantiate_templated_tag<in_place_index_t<Index>>::storage;
+
+#endif // __cpp_inline_variables >= 201606L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#endif // __cplusplus >= 201411L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#if defined(__cpp_lib_as_const) && __cpp_lib_as_const >= 201510L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::as_const;
+
+#else // Provide as_const polyfill.
+
+template <typename T>
+constexpr std::add_const_t<T>& as_const(T& t) noexcept {
+ return t;
+}
+
+template <typename T>
+void as_const(T&&) = delete;
+
+#endif // __cpp_lib_as_const >= 201510L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp17
+
+namespace cpp20 {
+
+#if defined(__cpp_lib_constexpr_algorithms) && __cpp_lib_constexpr_algorithms >= 201806L && \
+ !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::exchange;
+
+#else // Add swap constexpr polyfill.
+
+template <
+ typename T, typename U = T,
+ typename std::enable_if<std::is_move_assignable<T>::value && cpp17::is_assignable_v<T&, U>,
+ bool>::type = true>
+constexpr T exchange(T& obj, U&& new_value) {
+ T old = std::move(obj);
+ obj = std::forward<U>(new_value);
+ return old;
+}
+
+#endif // __cpp_lib_constexpr_algorithms >= 201806L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+} // namespace cpp20
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_UTILITY_H_
diff --git a/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/version.h b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/version.h
new file mode 100644
index 000000000..c022e4b30
--- /dev/null
+++ b/third_party/fuchsia/repo/sdk/lib/stdcompat/include/lib/stdcompat/version.h
@@ -0,0 +1,79 @@
+// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_VERSION_H_
+#define LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_VERSION_H_
+
+// This <version> polyfills is meant to provide the feature testing macros for the rest of
+// the stdcompat library. It is not meant to be a full polyfill of <version>.
+
+#if __has_include(<version>) && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+#include <version>
+#elif __cplusplus > 201703L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+#error "cpp=std20 must provide a '<version>' header."
+#else
+
+#if __has_include(<optional>) && !defined(__cpp_lib_optional) && __cplusplus >= 201606L
+#define __cpp_lib_optional 201606L
+#endif
+
+#if __has_include(<string_view>) && !defined(__cpp_lib_string_view) && __cplusplus >= 201606L
+#define __cpp_lib_string_view 201606L
+#endif
+
+#if __has_include(<variant>) && !defined(__cpp_lib_variant) && __cplusplus >= 201606L
+#define __cpp_lib_variant 201606L
+#endif
+
+#if !defined(__cpp_lib_void_t) && __cplusplus >= 201411L
+#define __cpp_lib_void_t 201411L
+#endif
+
+#if !defined(__cpp_lib_logical_traits) && __cplusplus >= 201510L
+#define __cpp_lib_logical_traits 201510L
+#endif
+
+#if !defined(__cpp_lib_addressof_constexpr) && __cplusplus >= 201603L
+#define __cpp_lib_addressof_constexpr 201603L
+#endif
+
+#if !defined(__cpp_lib_nonmember_container_access) && __cplusplus >= 201411L
+#define __cpp_lib_nonmember_container_access 201411L
+#endif
+
+#if !defined(__cpp_lib_byte) && __cplusplus >= 201603L
+#define __cpp_lib_byte 201603L
+#endif
+
+#if !defined(__cpp_lib_bool_constant) && __cplusplus >= 201505L
+#define __cpp_lib_bool_constant 201505L
+#endif
+
+#if !defined(__cpp_lib_type_trait_variable_templates) && __cplusplus >= 201510L
+#define __cpp_lib_type_trait_variable_templates 201510L
+#endif
+
+#if !defined(__cpp_lib_is_aggregate) && __cplusplus >= 201703L
+#define __cpp_lib_is_aggregate 201703L
+#endif
+
+#if !defined(__cpp_lib_is_invocable) && __cplusplus >= 201703L
+#define __cpp_lib_is_invocable 201703L
+#endif
+
+#if !defined(__cpp_lib_invoke) && __cplusplus >= 201411L
+#define __cpp_lib_invoke 201411L
+#endif
+
+#if !defined(__cpp_lib_apply) && __cplusplus >= 201603L
+#define __cpp_lib_apply 201603L
+#endif
+
+#if !defined(__cpp_lib_as_const) && __cplusplus >= 201510L
+#define __cpp_lib_as_const 201510L
+#endif
+
+#endif // __has_include(<version>) && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+#endif // LIB_STDCOMPAT_INCLUDE_LIB_STDCOMPAT_VERSION_H_