[libcxx-commits] [libcxx] [libc++] Implement the `<type_traits>` parts of P1317R2 (PR #151480)
A. Jiang via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Aug 5 04:23:59 PDT 2025
https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/151480
>From 6cf03e7ba074fb6eb2f7ee556ac0e130bddcc52c Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Thu, 31 Jul 2025 17:26:24 +0800
Subject: [PATCH 1/2] [libc++] Implement the `<type_traits>` parts of P1317R2
Changes of `std::apply` are still blocked on related changes in P2165R4.
---
libcxx/docs/ReleaseNotes/22.rst | 2 +
libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__type_traits/is_applicable.h | 115 +++
libcxx/include/module.modulemap.in | 4 +
libcxx/include/type_traits | 16 +
libcxx/modules/std/type_traits.inc | 18 +
.../type_traits/no_specializations.verify.cpp | 9 +-
...ed_from_integral_constant.compile.pass.cpp | 2 +
.../meta.rel/is_applicable.compile.pass.cpp | 598 ++++++++++++++++
.../is_nothrow_applicable.compile.pass.cpp | 652 ++++++++++++++++++
.../apply_result.compile.pass.cpp | 629 +++++++++++++++++
12 files changed, 2046 insertions(+), 2 deletions(-)
create mode 100644 libcxx/include/__type_traits/is_applicable.h
create mode 100644 libcxx/test/std/utilities/meta/meta.rel/is_applicable.compile.pass.cpp
create mode 100644 libcxx/test/std/utilities/meta/meta.rel/is_nothrow_applicable.compile.pass.cpp
create mode 100644 libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/apply_result.compile.pass.cpp
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 15bf46d44b07f..05c375359a688 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -38,6 +38,8 @@ What's New in Libc++ 22.0.0?
Implemented Papers
------------------
+- P1317R2: Remove return type deduction in ``std::apply`` (`Github <https://github.com/llvm/llvm-project/issues/148183>`__)
+ (Only components in ``<type_traits>`` are implemented.)
- P2321R2: ``zip`` (`Github <https://github.com/llvm/llvm-project/issues/105169>`__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release)
Improvements and New Features
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index febb0c176f9c4..99be92021434e 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -155,5 +155,5 @@
"`P2781R9 <https://wg21.link/P2781R9>`__","``std::constant_wrapper``","2025-06 (Sofia)","","",""
"`P3697R1 <https://wg21.link/P3697R1>`__","Minor additions to C++26 standard library hardening","2025-06 (Sofia)","","",""
"`P3552R3 <https://wg21.link/P3552R3>`__","Add a Coroutine Task Type","2025-06 (Sofia)","","",""
-"`P1317R2 <https://wg21.link/P1317R2>`__","Remove return type deduction in ``std::apply``","2025-06 (Sofia)","","",""
+"`P1317R2 <https://wg21.link/P1317R2>`__","Remove return type deduction in ``std::apply``","2025-06 (Sofia)","|In Progress|","",""
"","","","","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 51444ec668e2b..a823a2f3a7a50 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -819,6 +819,7 @@ set(files
__type_traits/is_aggregate.h
__type_traits/is_allocator.h
__type_traits/is_always_bitcastable.h
+ __type_traits/is_applicable.h
__type_traits/is_arithmetic.h
__type_traits/is_array.h
__type_traits/is_assignable.h
diff --git a/libcxx/include/__type_traits/is_applicable.h b/libcxx/include/__type_traits/is_applicable.h
new file mode 100644
index 0000000000000..00db70ac072b2
--- /dev/null
+++ b/libcxx/include/__type_traits/is_applicable.h
@@ -0,0 +1,115 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___TYPE_TRAITS_IS_APPLICABLE_H
+#define _LIBCPP___TYPE_TRAITS_IS_APPLICABLE_H
+
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__fwd/get.h>
+#include <__tuple/tuple_like.h>
+#include <__tuple/tuple_size.h>
+#include <__type_traits/conjunction.h>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/invoke.h>
+#include <__type_traits/remove_reference.h>
+#include <__utility/declval.h>
+#include <__utility/integer_sequence.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <class _Fn, class _Tuple>
+struct __apply_result_disabled_base {};
+
+template <class _Fn, class _Tuple, class _Tp>
+struct __apply_result_enabled_base {
+ using type _LIBCPP_NODEBUG = _Tp;
+};
+
+template <bool _Applicable, bool _Nothrow, class _Tp>
+struct __applicability_traits {
+ static constexpr bool __applicable = true;
+ static constexpr bool __nothrow_applicable = _Nothrow;
+
+ template <class _Fn, class _Tuple>
+ using __base_type _LIBCPP_NODEBUG = __apply_result_enabled_base<_Fn, _Tuple, _Tp>;
+};
+
+template <bool _Nothrow, class _Tp>
+struct __applicability_traits<false, _Nothrow, _Tp> {
+ static_assert(!_Nothrow, "misspecified [_Applicable = false, _Nothrow = true]");
+ static constexpr bool __applicable = false;
+ static constexpr bool __nothrow_applicable = false;
+
+ template <class _Fn, class _Tuple>
+ using __base_type _LIBCPP_NODEBUG = __apply_result_disabled_base<_Fn, _Tuple>;
+};
+
+template <class _Fn, class _Tuple, size_t... _Is>
+concept __tuple_applicable_impl = requires(_Tuple&& __tuple) {
+ [](auto&&...) {}(std::get<_Is>(static_cast<_Tuple &&>(__tuple))...);
+} && __is_invocable_v<_Fn, decltype(std::get<_Is>(std::declval<_Tuple>()))...>;
+
+template <class _Fn, class _Tuple, size_t... _Is>
+concept __tuple_nothrow_applicable_impl = requires(_Tuple&& __tuple) {
+ {
+ [](auto&&...) noexcept {}(std::get<_Is>(static_cast<_Tuple &&>(__tuple))...)
+ } noexcept;
+} && __is_nothrow_invocable_v<_Fn, decltype(std::get<_Is>(std::declval<_Tuple>()))...>;
+
+template <class _Fn, class _Tuple>
+consteval auto __applicability_traits_of() {
+ if constexpr (__tuple_like<_Tuple>)
+ return []<size_t... _Is>(index_sequence<_Is...>) {
+ if constexpr (__tuple_applicable_impl<_Fn, _Tuple, _Is...>) {
+ return __applicability_traits<
+ true,
+ __tuple_nothrow_applicable_impl<_Fn, _Tuple, _Is...>,
+ // FIXME: Use __invoke_result_y after merging https://github.com/llvm/llvm-project/pull/151028.
+ typename __invoke_result<_Fn, decltype(std::get<_Is>(std::declval<_Tuple>()))...>::type>{};
+ } else
+ return __applicability_traits<false, false, void>{};
+ }(make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>{});
+ else
+ return __applicability_traits<false, false, void>{};
+}
+
+template <class _Fn, class _Tuple>
+struct _LIBCPP_NO_SPECIALIZATIONS is_applicable
+ : bool_constant<decltype(std::__applicability_traits_of<_Fn, _Tuple>())::__applicable> {};
+
+template <class _Fn, class _Tuple>
+struct _LIBCPP_NO_SPECIALIZATIONS is_nothrow_applicable
+ : bool_constant<decltype(std::__applicability_traits_of<_Fn, _Tuple>())::__nothrow_applicable> {};
+
+template <class _Fn, class _Tuple>
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_applicable_v =
+ decltype(std::__applicability_traits_of<_Fn, _Tuple>())::__applicable;
+
+template <class _Fn, class _Tuple>
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_applicable_v =
+ decltype(std::__applicability_traits_of<_Fn, _Tuple>())::__nothrow_applicable;
+
+template <class _Fn, class _Tuple>
+struct _LIBCPP_NO_SPECIALIZATIONS apply_result
+ : decltype(std::__applicability_traits_of<_Fn, _Tuple>())::template __base_type<_Fn, _Tuple> {};
+
+template <class _Fn, class _Tuple>
+using apply_result_t = apply_result<_Fn, _Tuple>::type;
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TYPE_TRAITS_IS_APPLICABLE_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 5857a83b5fe14..6766960144a83 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -112,6 +112,10 @@ module std_core [system] {
header "__type_traits/is_always_bitcastable.h"
export std_core.type_traits.integral_constant
}
+ module is_applicable {
+ header "__type_traits/is_applicable.h"
+ export std_core.type_traits.integral_constant
+ }
module is_arithmetic {
header "__type_traits/is_arithmetic.h"
export std_core.type_traits.integral_constant
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index a6e0c1867566b..f8c3f744e07f4 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -168,6 +168,10 @@ namespace std
template <class R, class Fn, class... ArgTypes>
struct is_nothrow_invocable_r; // since C++17
+ template<class Fn, class Tuple> struct is_applicable; // since C++26
+ template<class Fn, class Tuple>
+ struct is_nothrow_applicable; // since C++26
+
// Alignment properties and transformations:
template <class T> struct alignment_of;
template <size_t Len, size_t Align = most_stringent_alignment_requirement>
@@ -183,6 +187,7 @@ namespace std
struct result_of<Fn(ArgTypes...)>; // deprecated in C++17; removed in C++20
template <class Fn, class... ArgTypes>
struct invoke_result; // since C++17
+ template<class Fn, class Tuple> struct apply_result; // since C++26
// const-volatile modifications:
template <class T>
@@ -265,6 +270,9 @@ namespace std
template <class Fn, class... ArgTypes>
using invoke_result_t
= typename invoke_result<Fn, ArgTypes...>::type; // since C++17
+ template <class Fn, class... ArgTypes>
+ using apply_result_t
+ = typename invoke_result<Fn, ArgTypes...>::type; // since C++26
template <class...>
using void_t = void; // since C++17
@@ -442,6 +450,10 @@ namespace std
= is_nothrow_invocable<Fn, ArgTypes...>::value; // since C++17
template <class R, class Fn, class... ArgTypes> inline constexpr bool is_nothrow_invocable_r_v
= is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; // since C++17
+ template<class Fn, class Tuple> constexpr bool is_applicable_v
+ = is_applicable<Fn, Tuple>::value; // since C++26
+ template<class Fn, class Tuple> constexpr bool is_nothrow_applicable_v
+ = is_nothrow_applicable<Fn, Tuple>::value; // since C++26
// [meta.logical], logical operator traits:
template<class... B> struct conjunction; // since C++17
@@ -559,6 +571,10 @@ namespace std
# include <__type_traits/reference_converts_from_temporary.h>
# endif
+# if _LIBCPP_STD_VER >= 26
+# include <__type_traits/is_applicable.h>
+# endif
+
# include <version>
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index 6823c86ed153b..0ad2bb4bea27f 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -121,6 +121,9 @@ export namespace std {
using std::rank;
// [meta.rel], type relations
+#if _LIBCPP_STD_VER >= 26
+ using std::is_applicable;
+#endif
using std::is_base_of;
#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_is_virtual_base_of)
using std::is_virtual_base_of;
@@ -134,6 +137,9 @@ export namespace std {
using std::is_invocable;
using std::is_invocable_r;
+#if _LIBCPP_STD_VER >= 26
+ using std::is_nothrow_applicable;
+#endif
using std::is_nothrow_invocable;
using std::is_nothrow_invocable_r;
@@ -183,6 +189,9 @@ export namespace std {
using std::remove_pointer_t;
// [meta.trans.other], other transformations
+#if _LIBCPP_STD_VER >= 26
+ using std::apply_result;
+#endif
using std::basic_common_reference;
using std::common_reference;
using std::common_type;
@@ -196,6 +205,9 @@ export namespace std {
using std::unwrap_ref_decay;
using std::unwrap_reference;
+#if _LIBCPP_STD_VER >= 26
+ using std::apply_result_t;
+#endif
using std::common_reference_t;
using std::common_type_t;
using std::conditional_t;
@@ -305,6 +317,9 @@ export namespace std {
using std::rank_v;
// [meta.rel], type relations
+#if _LIBCPP_STD_VER >= 26
+ using std::is_applicable_v;
+#endif
using std::is_base_of_v;
#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_is_virtual_base_of)
using std::is_virtual_base_of_v;
@@ -313,6 +328,9 @@ export namespace std {
using std::is_invocable_r_v;
using std::is_invocable_v;
// using std::is_layout_compatible_v;
+#if _LIBCPP_STD_VER >= 26
+ using std::is_nothrow_applicable_v;
+#endif
using std::is_nothrow_convertible_v;
using std::is_nothrow_invocable_r_v;
using std::is_nothrow_invocable_v;
diff --git a/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp b/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp
index 897ae89365014..b76a75a3b1584 100644
--- a/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp
+++ b/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp
@@ -53,6 +53,11 @@ SPECIALIZE_TRAIT(unwrap_reference); // expected-error {{cannot be specialized}}
SPECIALIZE_TRAIT(unwrap_ref_decay); // expected-error {{cannot be specialized}}
# endif
+# if TEST_STD_VER >= 26
+template <>
+struct std::apply_result<S, S>; // expected-error {{cannot be specialized}}
+# endif
+
# undef SPECIALIZE_TRAIT
# define SPECIALIZE_UTT(Trait) \
template <> \
@@ -165,7 +170,9 @@ SPECIALIZE_BTT(reference_converts_from_temporary); // expected-error 2 {{cannot
# endif
# if TEST_STD_VER >= 26
-SPECIALIZE_BTT(is_virtual_base_of); // expected-error 2 {{cannot be specialized}}
+SPECIALIZE_BTT(is_applicable); // expected-error 2 {{cannot be specialized}}
+SPECIALIZE_BTT(is_nothrow_applicable); // expected-error 2 {{cannot be specialized}}
+SPECIALIZE_BTT(is_virtual_base_of); // expected-error 2 {{cannot be specialized}}
# endif
# undef SPECIALIZE_UTT
diff --git a/libcxx/test/std/utilities/meta/derived_from_integral_constant.compile.pass.cpp b/libcxx/test/std/utilities/meta/derived_from_integral_constant.compile.pass.cpp
index 3db7a214b27bd..eb021f5840c6c 100644
--- a/libcxx/test/std/utilities/meta/derived_from_integral_constant.compile.pass.cpp
+++ b/libcxx/test/std/utilities/meta/derived_from_integral_constant.compile.pass.cpp
@@ -113,4 +113,6 @@ static_assert(std::is_base_of<std::false_type, std::is_scoped_enum<int>>::value,
# if defined(__cpp_lib_is_virtual_base_of) && __cpp_lib_is_virtual_base_of >= 202406L
static_assert(std::is_base_of<std::false_type, std::is_virtual_base_of<int, int>>::value, "");
# endif
+static_assert(std::is_base_of<std::false_type, std::is_applicable<int, int>>::value, "");
+static_assert(std::is_base_of<std::false_type, std::is_nothrow_applicable<int, int>>::value, "");
#endif
diff --git a/libcxx/test/std/utilities/meta/meta.rel/is_applicable.compile.pass.cpp b/libcxx/test/std/utilities/meta/meta.rel/is_applicable.compile.pass.cpp
new file mode 100644
index 0000000000000..7f70f19044d0f
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.rel/is_applicable.compile.pass.cpp
@@ -0,0 +1,598 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <type_traits>
+
+// template<class Fn, class Tuple> struct is_applicable;
+
+// template<class Fn, class Tuple>
+// constexpr bool is_applicable_v = is_applicable<T, U>::value;
+
+#include <cassert>
+#include <cstddef>
+#include <array>
+#include <complex>
+#include <ranges>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "callable_types.h"
+#include "test_iterators.h"
+
+struct empty_aggregate {};
+
+struct derived_from_tuple_int : std::tuple<int> {};
+
+template <>
+struct std::tuple_size<derived_from_tuple_int> : std::integral_constant<std::size_t, 1> {};
+
+template <std::size_t I>
+ requires(I < 1)
+struct std::tuple_element<I, derived_from_tuple_int> {
+ using type = std::tuple_element_t<I, std::tuple<int>>;
+};
+
+template <class Fn, class Tuple, bool Expected>
+void test_is_applicable() {
+ static_assert(std::is_applicable<Fn, Tuple>::value == Expected);
+ static_assert(std::is_applicable_v<Fn, Tuple> == Expected);
+
+ static_assert(std::is_base_of_v<std::bool_constant<Expected>, std::is_applicable<Fn, Tuple>>);
+ static_assert(std::is_convertible_v<std::is_applicable<Fn, Tuple>*, std::bool_constant<Expected>*>);
+}
+
+template <class Func, class Tuple, bool Expected>
+void test_is_applicable_from_function() {
+ static_assert(std::is_function_v<Func>);
+
+ test_is_applicable<Func, Tuple, Expected>();
+ test_is_applicable<Func&, Tuple, Expected>();
+
+ test_is_applicable<Func*, Tuple, Expected>();
+ test_is_applicable<Func*&, Tuple, Expected>();
+ test_is_applicable<Func* const, Tuple, Expected>();
+ test_is_applicable<Func* const&, Tuple, Expected>();
+ test_is_applicable<Func* volatile, Tuple, Expected>();
+ test_is_applicable<Func* volatile&, Tuple, Expected>();
+ test_is_applicable<Func* const volatile, Tuple, Expected>();
+ test_is_applicable<Func* const volatile&, Tuple, Expected>();
+}
+
+void test_valid() {
+ // test array
+ test_is_applicable_from_function<int(), std::array<int, 0>, true>();
+ test_is_applicable_from_function<int(), std::array<long, 0>&, true>();
+ test_is_applicable_from_function<int(), const std::array<char, 0>, true>();
+ test_is_applicable_from_function<int(), const std::array<std::array<int, 1>, 0>&, true>();
+ test_is_applicable_from_function<int() noexcept, std::array<int, 0>, true>();
+ test_is_applicable_from_function<int() noexcept, std::array<long, 0>&, true>();
+ test_is_applicable_from_function<int() noexcept, const std::array<char, 0>, true>();
+ test_is_applicable_from_function<int() noexcept, const std::array<std::array<int, 1>, 0>&, true>();
+
+ test_is_applicable_from_function<int(long), std::array<int, 1>, true>();
+ test_is_applicable_from_function<int&(int), std::array<long, 1>&, true>();
+ test_is_applicable_from_function<const int && (float), const std::array<double, 1>, true>();
+ test_is_applicable_from_function<void(double), const std::array<char, 1>&, true>();
+ test_is_applicable_from_function<int(long) noexcept, std::array<int, 1>, true>();
+ test_is_applicable_from_function<int&(int) noexcept, std::array<long, 1>&, true>();
+ test_is_applicable_from_function<const int && (float) noexcept, const std::array<double, 1>, true>();
+ test_is_applicable_from_function<void(double) noexcept, const std::array<char, 1>&, true>();
+
+ test_is_applicable_from_function<int(long, int), std::array<int, 2>, true>();
+ test_is_applicable_from_function<int&(long, int), std::array<int, 2>&, true>();
+ test_is_applicable_from_function<const int && (long, int), const std::array<int, 2>, true>();
+ test_is_applicable_from_function<void(long, int), const std::array<int, 2>&, true>();
+ test_is_applicable_from_function<int(long, int) noexcept, std::array<int, 2>, true>();
+ test_is_applicable_from_function<int&(long, int) noexcept, std::array<int, 2>&, true>();
+ test_is_applicable_from_function<const int && (long, int) noexcept, const std::array<int, 2>, true>();
+ test_is_applicable_from_function<void(long, int) noexcept, const std::array<int, 2>&, true>();
+
+ test_is_applicable<ConstCallable<bool>, std::array<int, 0>, true>();
+ test_is_applicable<ConstCallable<bool>, std::array<int, 1>&, true>();
+ test_is_applicable<ConstCallable<bool>, const std::array<int, 2>, true>();
+ test_is_applicable<ConstCallable<bool>, const std::array<int, 3>&, true>();
+
+ test_is_applicable<NoExceptCallable<bool>, std::array<int, 0>, true>();
+ test_is_applicable<NoExceptCallable<bool>, std::array<int, 1>&, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::array<int, 2>, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::array<int, 3>&, true>();
+
+ // test complex
+ test_is_applicable_from_function<float(float, float), std::complex<float>, true>();
+ test_is_applicable_from_function<float(float&, float&), std::complex<float>&, true>();
+ test_is_applicable_from_function<void(float, float), const std::complex<float>, true>();
+ test_is_applicable_from_function<double(float, float), const std::complex<float>&, true>();
+ test_is_applicable_from_function<float(float, float) noexcept, std::complex<float>, true>();
+ test_is_applicable_from_function<float(float&, float&) noexcept, std::complex<float>&, true>();
+ test_is_applicable_from_function<void(float, float) noexcept, const std::complex<float>, true>();
+ test_is_applicable_from_function<double(float, float) noexcept, const std::complex<float>&, true>();
+
+ test_is_applicable<ConstCallable<bool>, std::complex<float>, true>();
+ test_is_applicable<ConstCallable<bool>, std::complex<float>&, true>();
+ test_is_applicable<ConstCallable<bool>, const std::complex<float>, true>();
+ test_is_applicable<ConstCallable<bool>, const std::complex<float>&, true>();
+
+ test_is_applicable<NoExceptCallable<bool>, std::complex<float>, true>();
+ test_is_applicable<NoExceptCallable<bool>, std::complex<float>&, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::complex<float>, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::complex<float>&, true>();
+
+ test_is_applicable_from_function<double(double, double), std::complex<double>, true>();
+ test_is_applicable_from_function<double&(double&, double&), std::complex<double>&, true>();
+ test_is_applicable_from_function<void(double, double), const std::complex<double>, true>();
+ test_is_applicable_from_function<double(double, double), const std::complex<double>&, true>();
+ test_is_applicable_from_function<double(double, double) noexcept, std::complex<double>, true>();
+ test_is_applicable_from_function<double&(double&, double&) noexcept, std::complex<double>&, true>();
+ test_is_applicable_from_function<void(double, double) noexcept, const std::complex<double>, true>();
+ test_is_applicable_from_function<double(double, double) noexcept, const std::complex<double>&, true>();
+
+ test_is_applicable<ConstCallable<bool>, std::complex<double>, true>();
+ test_is_applicable<ConstCallable<bool>, std::complex<double>&, true>();
+ test_is_applicable<ConstCallable<bool>, const std::complex<double>, true>();
+ test_is_applicable<ConstCallable<bool>, const std::complex<double>&, true>();
+
+ test_is_applicable<NoExceptCallable<bool>, std::complex<double>, true>();
+ test_is_applicable<NoExceptCallable<bool>, std::complex<double>&, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::complex<double>, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::complex<double>&, true>();
+
+ test_is_applicable_from_function<long double(long double, long double), std::complex<long double>, true>();
+ test_is_applicable_from_function<long double&(long double&, long double&), std::complex<long double>&, true>();
+ test_is_applicable_from_function<void(long double, long double), const std::complex<long double>, true>();
+ test_is_applicable_from_function<double(long double, long double), const std::complex<long double>&, true>();
+ test_is_applicable_from_function<long double(long double, long double) noexcept, std::complex<long double>, true>();
+ test_is_applicable_from_function<long double&(long double&, long double&) noexcept,
+ std::complex<long double>&,
+ true>();
+ test_is_applicable_from_function<void(long double, long double) noexcept, const std::complex<long double>, true>();
+ test_is_applicable_from_function<double(long double, long double) noexcept, const std::complex<long double>&, true>();
+
+ test_is_applicable<ConstCallable<bool>, std::complex<long double>, true>();
+ test_is_applicable<ConstCallable<bool>, std::complex<long double>&, true>();
+ test_is_applicable<ConstCallable<bool>, const std::complex<long double>, true>();
+ test_is_applicable<ConstCallable<bool>, const std::complex<long double>&, true>();
+
+ test_is_applicable<NoExceptCallable<bool>, std::complex<long double>, true>();
+ test_is_applicable<NoExceptCallable<bool>, std::complex<long double>&, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::complex<long double>, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::complex<long double>&, true>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_is_applicable_from_function<void(int*, int*), copyable_subrange, true>();
+ test_is_applicable_from_function<long(int*, int*), copyable_subrange&, true>();
+ test_is_applicable_from_function<int*&(int*, int*), const copyable_subrange, true>();
+ test_is_applicable_from_function<int* && (int*, int*), const copyable_subrange&, true>();
+ test_is_applicable_from_function<void(int*, int*) noexcept, copyable_subrange, true>();
+ test_is_applicable_from_function<long(int*, int*) noexcept, copyable_subrange&, true>();
+ test_is_applicable_from_function<int*&(int*, int*) noexcept, const copyable_subrange, true>();
+ test_is_applicable_from_function<int* && (int*, int*) noexcept, const copyable_subrange&, true>();
+
+ test_is_applicable<ConstCallable<bool>, copyable_subrange, true>();
+ test_is_applicable<ConstCallable<bool>, copyable_subrange&, true>();
+ test_is_applicable<ConstCallable<bool>, const copyable_subrange, true>();
+ test_is_applicable<ConstCallable<bool>, const copyable_subrange&, true>();
+
+ test_is_applicable<NoExceptCallable<bool>, copyable_subrange, true>();
+ test_is_applicable<NoExceptCallable<bool>, copyable_subrange&, true>();
+ test_is_applicable<NoExceptCallable<bool>, const copyable_subrange, true>();
+ test_is_applicable<NoExceptCallable<bool>, const copyable_subrange&, true>();
+
+ using move_only_counted_iter = std::counted_iterator<cpp20_input_iterator<int*>>;
+ using move_only_subrange = std::ranges::subrange<move_only_counted_iter, std::default_sentinel_t>;
+
+ test_is_applicable_from_function<void(move_only_counted_iter&&, std::default_sentinel_t), move_only_subrange, true>();
+ test_is_applicable_from_function<void(move_only_counted_iter&&, std::default_sentinel_t) noexcept,
+ move_only_subrange,
+ true>();
+
+ test_is_applicable<ConstCallable<bool>, move_only_subrange, true >();
+
+ test_is_applicable<NoExceptCallable<bool>, move_only_subrange, true>();
+
+ // test tuple
+ test_is_applicable_from_function<int(), std::tuple<>, true>();
+ test_is_applicable_from_function<char&(), std::tuple<>&, true>();
+ test_is_applicable_from_function<long && (), const std::tuple<>, true>();
+ test_is_applicable_from_function<void(), const std::tuple<>&, true>();
+ test_is_applicable_from_function<int() noexcept, std::tuple<>, true>();
+ test_is_applicable_from_function<char&() noexcept, std::tuple<>&, true>();
+ test_is_applicable_from_function<long && () noexcept, const std::tuple<>, true>();
+ test_is_applicable_from_function<void() noexcept, const std::tuple<>&, true>();
+
+ test_is_applicable_from_function<int(long, int), std::tuple<int, long>, true>();
+ test_is_applicable_from_function<int&(long, int), std::tuple<int, long>&, true>();
+ test_is_applicable_from_function<const int && (long, int), const std::tuple<int, long>, true>();
+ test_is_applicable_from_function<void(long, int), const std::tuple<int, long>&, true>();
+ test_is_applicable_from_function<int(long, int) noexcept, std::tuple<int, long>, true>();
+ test_is_applicable_from_function<int&(long, int) noexcept, std::tuple<int, long>&, true>();
+ test_is_applicable_from_function<const int && (long, int) noexcept, const std::tuple<int, long>, true>();
+ test_is_applicable_from_function<void(long, int) noexcept, const std::tuple<int, long>&, true>();
+
+ test_is_applicable<ConstCallable<bool>, std::tuple<>, true>();
+ test_is_applicable<ConstCallable<bool>, std::tuple<long>&, true>();
+ test_is_applicable<ConstCallable<bool>, const std::tuple<int, long>, true>();
+ test_is_applicable<ConstCallable<bool>, const std::tuple<int, double, long>&, true>();
+
+ test_is_applicable<NoExceptCallable<bool>, std::tuple<>, true>();
+ test_is_applicable<NoExceptCallable<bool>, std::tuple<long>&, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::tuple<int, long>, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::tuple<int, double, long>&, true>();
+
+ // test pair
+ test_is_applicable_from_function<int(long, int), std::pair<int, long>, true>();
+ test_is_applicable_from_function<int&(long, int), std::pair<int, long>&, true>();
+ test_is_applicable_from_function<const int && (long, int), const std::pair<int, long>, true>();
+ test_is_applicable_from_function<void(long, int), const std::pair<int, long>&, true>();
+ test_is_applicable_from_function<int(long, int) noexcept, std::pair<int, long>, true>();
+ test_is_applicable_from_function<int&(long, int) noexcept, std::pair<int, long>&, true>();
+ test_is_applicable_from_function<const int && (long, int) noexcept, const std::pair<int, long>, true>();
+ test_is_applicable_from_function<void(long, int) noexcept, const std::pair<int, long>&, true>();
+
+ test_is_applicable<ConstCallable<bool>, std::pair<char, wchar_t>, true>();
+ test_is_applicable<ConstCallable<bool>, std::pair<float, long>&, true>();
+ test_is_applicable<ConstCallable<bool>, const std::pair<int, long>, true>();
+ test_is_applicable<ConstCallable<bool>, const std::pair<int, double>&, true>();
+
+ test_is_applicable<NoExceptCallable<bool>, std::pair<char, wchar_t>, true>();
+ test_is_applicable<NoExceptCallable<bool>, std::pair<float, long>&, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::pair<int, long>, true>();
+ test_is_applicable<NoExceptCallable<bool>, const std::pair<int, double>&, true>();
+}
+
+void test_volatile() {
+ // test array
+ test_is_applicable_from_function<void(int), volatile std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int), volatile std::array<int, 1>&, false>();
+ test_is_applicable_from_function<void(int), const volatile std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int), const volatile std::array<int, 1>&, false>();
+ test_is_applicable_from_function<void(int) noexcept, volatile std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int) noexcept, volatile std::array<int, 1>&, false>();
+ test_is_applicable_from_function<void(int) noexcept, const volatile std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int) noexcept, const volatile std::array<int, 1>&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, volatile std::array<int, 1>, false>();
+ test_is_applicable<NoExceptCallable<bool>, volatile std::array<int, 1>&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::array<int, 1>, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::array<int, 1>&, false>();
+
+ // test complex
+ test_is_applicable_from_function<void(double, double), volatile std::complex<double>, false>();
+ test_is_applicable_from_function<void(double, double), volatile std::complex<double>&, false>();
+ test_is_applicable_from_function<void(double, double), const volatile std::complex<double>, false>();
+ test_is_applicable_from_function<void(double, double), const volatile std::complex<double>&, false>();
+ test_is_applicable_from_function<void(double, double) noexcept, volatile std::complex<double>, false>();
+ test_is_applicable_from_function<void(double, double) noexcept, volatile std::complex<double>&, false>();
+ test_is_applicable_from_function<void(double, double) noexcept, const volatile std::complex<double>, false>();
+ test_is_applicable_from_function<void(double, double) noexcept, const volatile std::complex<double>&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, volatile std::complex<double>, false>();
+ test_is_applicable<NoExceptCallable<bool>, volatile std::complex<double>&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::complex<double>, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::complex<double>&, false>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_is_applicable_from_function<void(int*, int*), volatile copyable_subrange, false>();
+ test_is_applicable_from_function<void(int*, int*), volatile copyable_subrange&, false>();
+ test_is_applicable_from_function<void(int*, int*), const volatile copyable_subrange, false>();
+ test_is_applicable_from_function<void(int*, int*), const volatile copyable_subrange&, false>();
+ test_is_applicable_from_function<void(int*, int*) noexcept, volatile copyable_subrange, false>();
+ test_is_applicable_from_function<void(int*, int*) noexcept, volatile copyable_subrange&, false>();
+ test_is_applicable_from_function<void(int*, int*) noexcept, const volatile copyable_subrange, false>();
+ test_is_applicable_from_function<void(int*, int*) noexcept, const volatile copyable_subrange&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, volatile copyable_subrange, false>();
+ test_is_applicable<NoExceptCallable<bool>, volatile copyable_subrange&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile copyable_subrange, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile copyable_subrange&, false>();
+
+ // test tuple
+ test_is_applicable_from_function<void(int, char*, double), volatile std::tuple<int, char*, double>, false>();
+ test_is_applicable_from_function<void(int, char*, double), volatile std::tuple<int, char*, double>&, false>();
+ test_is_applicable_from_function<void(int, char*, double), const volatile std::tuple<int, char*, double>, false>();
+ test_is_applicable_from_function<void(int, char*, double), const volatile std::tuple<int, char*, double>&, false>();
+ test_is_applicable_from_function<void(int, char*, double) noexcept, volatile std::tuple<int, char*, double>, false>();
+ test_is_applicable_from_function<void(int, char*, double) noexcept,
+ volatile std::tuple<int, char*, double>&,
+ false>();
+ test_is_applicable_from_function<void(int, char*, double) noexcept,
+ const volatile std::tuple<int, char*, double>,
+ false>();
+ test_is_applicable_from_function<void(int, char*, double) noexcept,
+ const volatile std::tuple<int, char*, double>&,
+ false>();
+
+ test_is_applicable<NoExceptCallable<bool>, volatile std::tuple<int, char*, double>, false>();
+ test_is_applicable<NoExceptCallable<bool>, volatile std::tuple<int, char*, double>&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::tuple<int, char*, double>, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::tuple<int, char*, double>&, false>();
+
+ // test pair
+ test_is_applicable_from_function<void(int, long), volatile std::pair<int, long>, false>();
+ test_is_applicable_from_function<void(int, long), volatile std::pair<int, long>&, false>();
+ test_is_applicable_from_function<void(int, long), const volatile std::pair<int, long>, false>();
+ test_is_applicable_from_function<void(int, long), const volatile std::pair<int, long>&, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, volatile std::pair<int, long>, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, volatile std::pair<int, long>&, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, const volatile std::pair<int, long>, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, const volatile std::pair<int, long>&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, volatile std::pair<int, long>, false>();
+ test_is_applicable<NoExceptCallable<bool>, volatile std::pair<int, long>&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::pair<int, long>, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile std::pair<int, long>&, false>();
+}
+
+void test_invalid_nontuple_types() {
+ // test void
+ test_is_applicable_from_function<void(), void, false>();
+ test_is_applicable_from_function<void(), const void, false>();
+ test_is_applicable_from_function<void(), volatile void, false>();
+ test_is_applicable_from_function<void(), const volatile void, false>();
+ test_is_applicable_from_function<void() noexcept, void, false>();
+ test_is_applicable_from_function<void() noexcept, const void, false>();
+ test_is_applicable_from_function<void() noexcept, volatile void, false>();
+ test_is_applicable_from_function<void() noexcept, const volatile void, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, void, false>();
+ test_is_applicable<NoExceptCallable<bool>, const void, false>();
+ test_is_applicable<NoExceptCallable<bool>, volatile void, false>();
+ test_is_applicable<NoExceptCallable<bool>, const volatile void, false>();
+
+ // test function
+ test_is_applicable_from_function<void(void (&)()), void(), false>();
+ test_is_applicable_from_function<void(void (&)()), void (&)(), false>();
+ test_is_applicable_from_function<void(void (&)()) noexcept, void(), false>();
+ test_is_applicable_from_function<void(void (&)()) noexcept, void (&)(), false>();
+ test_is_applicable_from_function<void(void (&)()), void() const & noexcept, false>();
+ test_is_applicable_from_function<void(void (&)()) noexcept, void() const & noexcept, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, void(), false>();
+ test_is_applicable<NoExceptCallable<bool>, void (&)(), false>();
+ test_is_applicable<NoExceptCallable<bool>, void() const & noexcept, false>();
+
+ // test scalar
+ test_is_applicable_from_function<void(int), int, false>();
+ test_is_applicable_from_function<void(int), int&, false>();
+ test_is_applicable_from_function<void(int), const int, false>();
+ test_is_applicable_from_function<void(int), const int&, false>();
+ test_is_applicable_from_function<void(int) noexcept, int, false>();
+ test_is_applicable_from_function<void(int) noexcept, int&, false>();
+ test_is_applicable_from_function<void(int) noexcept, const int, false>();
+ test_is_applicable_from_function<void(int) noexcept, const int&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, int, false>();
+ test_is_applicable<NoExceptCallable<bool>, int&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const int, false>();
+ test_is_applicable<NoExceptCallable<bool>, const int&, false>();
+
+ test_is_applicable_from_function<void(void*), void*, false>();
+ test_is_applicable_from_function<void(void*), void*&, false>();
+ test_is_applicable_from_function<void(void*), void* const, false>();
+ test_is_applicable_from_function<void(void*), void* const&, false>();
+ test_is_applicable_from_function<void(void*) noexcept, void*, false>();
+ test_is_applicable_from_function<void(void*) noexcept, void*&, false>();
+ test_is_applicable_from_function<void(void*) noexcept, void* const, false>();
+ test_is_applicable_from_function<void(void*) noexcept, void* const&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, void*, false>();
+ test_is_applicable<NoExceptCallable<bool>, void*&, false>();
+ test_is_applicable<NoExceptCallable<bool>, void* const, false>();
+ test_is_applicable<NoExceptCallable<bool>, void* const&, false>();
+
+ // test plain aggregate
+ test_is_applicable_from_function<void(), empty_aggregate, false>();
+ test_is_applicable_from_function<void(), empty_aggregate&, false>();
+ test_is_applicable_from_function<void(), const empty_aggregate, false>();
+ test_is_applicable_from_function<void(), const empty_aggregate&, false>();
+ test_is_applicable_from_function<void() noexcept, empty_aggregate, false>();
+ test_is_applicable_from_function<void() noexcept, empty_aggregate&, false>();
+ test_is_applicable_from_function<void() noexcept, const empty_aggregate, false>();
+ test_is_applicable_from_function<void() noexcept, const empty_aggregate&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, empty_aggregate, false>();
+ test_is_applicable<NoExceptCallable<bool>, empty_aggregate&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const empty_aggregate, false>();
+ test_is_applicable<NoExceptCallable<bool>, const empty_aggregate&, false>();
+
+ // test std::get-able class
+ test_is_applicable_from_function<void(int), derived_from_tuple_int, false>();
+ test_is_applicable_from_function<void(int), derived_from_tuple_int&, false>();
+ test_is_applicable_from_function<void(int), const derived_from_tuple_int, false>();
+ test_is_applicable_from_function<void(int), const derived_from_tuple_int&, false>();
+ test_is_applicable_from_function<void(int) noexcept, derived_from_tuple_int, false>();
+ test_is_applicable_from_function<void(int) noexcept, derived_from_tuple_int&, false>();
+ test_is_applicable_from_function<void(int) noexcept, const derived_from_tuple_int, false>();
+ test_is_applicable_from_function<void(int) noexcept, const derived_from_tuple_int&, false>();
+
+ test_is_applicable<NoExceptCallable<bool>, derived_from_tuple_int, false>();
+ test_is_applicable<NoExceptCallable<bool>, derived_from_tuple_int&, false>();
+ test_is_applicable<NoExceptCallable<bool>, const derived_from_tuple_int, false>();
+ test_is_applicable<NoExceptCallable<bool>, const derived_from_tuple_int&, false>();
+
+ // test built-in array
+ test_is_applicable_from_function<void(int), int[1], false>();
+ test_is_applicable_from_function<void(int), int (&)[1], false>();
+ test_is_applicable_from_function<void(int), const int[1], false>();
+ test_is_applicable_from_function<void(int), const int (&)[1], false>();
+ test_is_applicable_from_function<void(int) noexcept, int[1], false>();
+ test_is_applicable_from_function<void(int) noexcept, int (&)[1], false>();
+ test_is_applicable_from_function<void(int) noexcept, const int[1], false>();
+ test_is_applicable_from_function<void(int) noexcept, const int (&)[1], false>();
+
+ test_is_applicable<NoExceptCallable<bool>, int[1], false>();
+ test_is_applicable<NoExceptCallable<bool>, int (&)[1], false>();
+ test_is_applicable<NoExceptCallable<bool>, const int[1], false>();
+ test_is_applicable<NoExceptCallable<bool>, const int (&)[1], false>();
+}
+
+void test_invalid_invocations() {
+ // test array
+ test_is_applicable<void, std::array<int, 0>, false>();
+ test_is_applicable<void*, std::array<int, 1>, false>();
+ test_is_applicable<int, std::array<int, 2>, false>();
+ test_is_applicable<int&, std::array<int, 3>, false>();
+ test_is_applicable<int(int, int, int, int) const & noexcept, std::array<int, 4>, false>();
+
+ test_is_applicable_from_function<void(int), std::array<int, 0>, false>();
+ test_is_applicable_from_function<void(int), std::array<int, 0>&, false>();
+ test_is_applicable_from_function<void(int), const std::array<int, 0>, false>();
+ test_is_applicable_from_function<void(int), const std::array<int, 0>&, false>();
+ test_is_applicable_from_function<void(int) noexcept, std::array<int, 0>, false>();
+ test_is_applicable_from_function<void(int) noexcept, std::array<int, 0>&, false>();
+ test_is_applicable_from_function<void(int) noexcept, const std::array<int, 0>, false>();
+ test_is_applicable_from_function<void(int) noexcept, const std::array<int, 0>&, false>();
+ test_is_applicable_from_function<void(int, long), std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int, long), std::array<int, 1>&, false>();
+ test_is_applicable_from_function<void(int, long), const std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int, long), const std::array<int, 1>&, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, std::array<int, 1>&, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, const std::array<int, 1>, false>();
+ test_is_applicable_from_function<void(int, long) noexcept, const std::array<int, 1>&, false>();
+
+ // test complex
+ test_is_applicable<void, std::complex<float>, false>();
+ test_is_applicable<void*, std::complex<float>, false>();
+ test_is_applicable<int, std::complex<float>, false>();
+ test_is_applicable<int&, std::complex<float>, false>();
+ test_is_applicable<void(float, float) const & noexcept, std::complex<float>, false>();
+
+ test_is_applicable<void, std::complex<double>, false>();
+ test_is_applicable<void*, std::complex<double>, false>();
+ test_is_applicable<int, std::complex<double>, false>();
+ test_is_applicable<int&, std::complex<double>, false>();
+ test_is_applicable<void(double, double) const & noexcept, std::complex<double>, false>();
+
+ test_is_applicable<void, std::complex<long double>, false>();
+ test_is_applicable<void*, std::complex<long double>, false>();
+ test_is_applicable<int, std::complex<long double>, false>();
+ test_is_applicable<int&, std::complex<long double>, false>();
+ test_is_applicable<void(long double, long double) const & noexcept, std::complex<long double>, false>();
+
+ test_is_applicable_from_function<void(float), std::complex<float>, false>();
+ test_is_applicable_from_function<void(float), std::complex<float>&, false>();
+ test_is_applicable_from_function<void(float), const std::complex<float>, false>();
+ test_is_applicable_from_function<void(float), const std::complex<float>&, false>();
+ test_is_applicable_from_function<void(float) noexcept, std::complex<float>, false>();
+ test_is_applicable_from_function<void(float) noexcept, std::complex<float>&, false>();
+ test_is_applicable_from_function<void(float) noexcept, const std::complex<float>, false>();
+ test_is_applicable_from_function<void(float) noexcept, const std::complex<float>&, false>();
+
+ test_is_applicable_from_function<void(double), std::complex<double>, false>();
+ test_is_applicable_from_function<void(double), std::complex<double>&, false>();
+ test_is_applicable_from_function<void(double), const std::complex<double>, false>();
+ test_is_applicable_from_function<void(double), const std::complex<double>&, false>();
+ test_is_applicable_from_function<void(double) noexcept, std::complex<double>, false>();
+ test_is_applicable_from_function<void(double) noexcept, std::complex<double>&, false>();
+ test_is_applicable_from_function<void(double) noexcept, const std::complex<double>, false>();
+ test_is_applicable_from_function<void(double) noexcept, const std::complex<double>&, false>();
+
+ test_is_applicable_from_function<void(long double), std::complex<long double>, false>();
+ test_is_applicable_from_function<void(long double), std::complex<long double>&, false>();
+ test_is_applicable_from_function<void(long double), const std::complex<long double>, false>();
+ test_is_applicable_from_function<void(long double), const std::complex<long double>&, false>();
+ test_is_applicable_from_function<void(long double) noexcept, std::complex<long double>, false>();
+ test_is_applicable_from_function<void(long double) noexcept, std::complex<long double>&, false>();
+ test_is_applicable_from_function<void(long double) noexcept, const std::complex<long double>, false>();
+ test_is_applicable_from_function<void(long double) noexcept, const std::complex<long double>&, false>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_is_applicable<void, copyable_subrange, false>();
+ test_is_applicable<void*, copyable_subrange, false>();
+ test_is_applicable<int, copyable_subrange, false>();
+ test_is_applicable<int&, copyable_subrange, false>();
+
+ test_is_applicable_from_function<void(std::default_sentinel_t), copyable_subrange, false>();
+ test_is_applicable_from_function<void(std::default_sentinel_t), copyable_subrange&, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t), const copyable_subrange, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t), const copyable_subrange&, false>();
+ test_is_applicable_from_function<void(std::default_sentinel_t) noexcept, copyable_subrange, false>();
+ test_is_applicable_from_function<void(std::default_sentinel_t) noexcept, copyable_subrange&, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t) noexcept, const copyable_subrange, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t) noexcept, const copyable_subrange&, false>();
+
+ using move_only_counted_iter = std::counted_iterator<cpp20_input_iterator<int*>>;
+ using move_only_subrange = std::ranges::subrange<move_only_counted_iter, std::default_sentinel_t>;
+
+ test_is_applicable<void, move_only_subrange, false>();
+ test_is_applicable<void*, move_only_subrange, false>();
+ test_is_applicable<int, move_only_subrange, false>();
+ test_is_applicable<int&, move_only_subrange, false>();
+
+ test_is_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ move_only_subrange&,
+ false>();
+ test_is_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ const move_only_subrange,
+ false>();
+ test_is_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ const move_only_subrange&,
+ false>();
+ test_is_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ move_only_subrange&,
+ false>();
+ test_is_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ const move_only_subrange,
+ false>();
+ test_is_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ const move_only_subrange&,
+ false>();
+
+ test_is_applicable_from_function<void(std::default_sentinel_t), move_only_subrange, false>();
+ test_is_applicable_from_function<void(std::default_sentinel_t), move_only_subrange&, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t), const move_only_subrange, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t), const move_only_subrange&, false>();
+ test_is_applicable_from_function<void(std::default_sentinel_t) noexcept, move_only_subrange, false>();
+ test_is_applicable_from_function<void(std::default_sentinel_t) noexcept, move_only_subrange&, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t) noexcept, const move_only_subrange, false>();
+ test_is_applicable_from_function<int(std::default_sentinel_t) noexcept, const move_only_subrange&, false>();
+
+ // test tuple
+ test_is_applicable<void, std::tuple<>, false>();
+ test_is_applicable<void*, std::tuple<>, false>();
+ test_is_applicable<int, std::tuple<int>, false>();
+ test_is_applicable<int&, std::tuple<int>, false>();
+ test_is_applicable<int() const&, std::tuple<>, false>();
+ test_is_applicable<int() const & noexcept, std::tuple<>, false>();
+
+ test_is_applicable_from_function<int(), std::tuple<int>, false>();
+ test_is_applicable_from_function<int(), std::tuple<int>&, false>();
+ test_is_applicable_from_function<int(), const std::tuple<int>, false>();
+ test_is_applicable_from_function<int(), const std::tuple<int>&, false>();
+ test_is_applicable_from_function<int() noexcept, std::tuple<int>, false>();
+ test_is_applicable_from_function<int() noexcept, std::tuple<int>&, false>();
+ test_is_applicable_from_function<int() noexcept, const std::tuple<int>, false>();
+ test_is_applicable_from_function<int() noexcept, const std::tuple<int>&, false>();
+
+ // test pair
+ test_is_applicable<void, std::pair<int, long>, false>();
+ test_is_applicable<void*, std::pair<int, long>, false>();
+ test_is_applicable<int, std::pair<int, long>, false>();
+ test_is_applicable<int&, std::pair<int, long>, false>();
+
+ test_is_applicable<int(int, long) const&, std::pair<int, long>, false>();
+ test_is_applicable<int(int, long) const & noexcept, std::pair<int, long>, false>();
+
+ test_is_applicable_from_function<int(), std::pair<int, long>, false>();
+ test_is_applicable_from_function<void(int, long, long long), std::pair<int, long>&, false>();
+ test_is_applicable_from_function<int&(int), const std::pair<int, long>, false>();
+ test_is_applicable_from_function<long&(int&, long&), const std::pair<int, long>&, false>();
+ test_is_applicable_from_function<int() noexcept, std::pair<int, long>, false>();
+ test_is_applicable_from_function<void(int, long, long long) noexcept, std::pair<int, long>&, false>();
+ test_is_applicable_from_function<int&(int) noexcept, const std::pair<int, long>, false>();
+ test_is_applicable_from_function<long&(int&, long&) noexcept, const std::pair<int, long>&, false>();
+}
diff --git a/libcxx/test/std/utilities/meta/meta.rel/is_nothrow_applicable.compile.pass.cpp b/libcxx/test/std/utilities/meta/meta.rel/is_nothrow_applicable.compile.pass.cpp
new file mode 100644
index 0000000000000..de8c8a44c3396
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.rel/is_nothrow_applicable.compile.pass.cpp
@@ -0,0 +1,652 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <type_traits>
+
+// template<class Fn, class Tuple> struct is_nothrow_applicable;
+
+// template<class Fn, class Tuple>
+// constexpr bool is_nothrow_applicable_v = is_nothrow_applicable<T, U>::value;
+
+#include <cassert>
+#include <cstddef>
+#include <array>
+#include <complex>
+#include <ranges>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "callable_types.h"
+#include "test_iterators.h"
+
+struct empty_aggregate {};
+
+struct derived_from_tuple_int : std::tuple<int> {};
+
+template <>
+struct std::tuple_size<derived_from_tuple_int> : std::integral_constant<std::size_t, 1> {};
+
+template <std::size_t I>
+ requires(I < 1)
+struct std::tuple_element<I, derived_from_tuple_int> {
+ using type = std::tuple_element_t<I, std::tuple<int>>;
+};
+
+template <class Fn, class Tuple, bool Expected>
+void test_is_nothrow_applicable() {
+ static_assert(std::is_nothrow_applicable<Fn, Tuple>::value == Expected);
+ static_assert(std::is_nothrow_applicable_v<Fn, Tuple> == Expected);
+
+ static_assert(std::is_base_of_v<std::bool_constant<Expected>, std::is_nothrow_applicable<Fn, Tuple>>);
+ static_assert(std::is_convertible_v<std::is_nothrow_applicable<Fn, Tuple>*, std::bool_constant<Expected>*>);
+}
+
+template <class Func, class Tuple, bool Expected>
+void test_is_nothrow_applicable_from_function() {
+ static_assert(std::is_function_v<Func>);
+
+ test_is_nothrow_applicable<Func, Tuple, Expected>();
+ test_is_nothrow_applicable<Func&, Tuple, Expected>();
+
+ test_is_nothrow_applicable<Func*, Tuple, Expected>();
+ test_is_nothrow_applicable<Func*&, Tuple, Expected>();
+ test_is_nothrow_applicable<Func* const, Tuple, Expected>();
+ test_is_nothrow_applicable<Func* volatile, Tuple, Expected>();
+ test_is_nothrow_applicable<Func* volatile&, Tuple, Expected>();
+ test_is_nothrow_applicable<Func* const volatile, Tuple, Expected>();
+ test_is_nothrow_applicable<Func* const volatile&, Tuple, Expected>();
+}
+
+void test_valid() {
+ // test array
+ test_is_nothrow_applicable_from_function<int() noexcept, std::array<int, 0>, true>();
+ test_is_nothrow_applicable_from_function<int() noexcept, std::array<long, 0>&, true>();
+ test_is_nothrow_applicable_from_function<int() noexcept, const std::array<char, 0>, true>();
+ test_is_nothrow_applicable_from_function<int() noexcept, const std::array<std::array<int, 1>, 0>&, true>();
+
+ test_is_nothrow_applicable_from_function<int(long) noexcept, std::array<int, 1>, true>();
+ test_is_nothrow_applicable_from_function<int&(int) noexcept, std::array<long, 1>&, true>();
+ test_is_nothrow_applicable_from_function<const int && (float) noexcept, const std::array<double, 1>, true>();
+ test_is_nothrow_applicable_from_function<void(double) noexcept, const std::array<char, 1>&, true>();
+
+ test_is_nothrow_applicable_from_function<int(long, int) noexcept, std::array<int, 2>, true>();
+ test_is_nothrow_applicable_from_function<int&(long, int) noexcept, std::array<int, 2>&, true>();
+ test_is_nothrow_applicable_from_function<const int && (long, int) noexcept, const std::array<int, 2>, true>();
+ test_is_nothrow_applicable_from_function<void(long, int) noexcept, const std::array<int, 2>&, true>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::array<int, 0>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::array<int, 1>&, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::array<int, 2>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::array<int, 3>&, true>();
+
+ // test complex
+ test_is_nothrow_applicable_from_function<float(float, float) noexcept, std::complex<float>, true>();
+ test_is_nothrow_applicable_from_function<float(float&, float&) noexcept, std::complex<float>&, true>();
+ test_is_nothrow_applicable_from_function<void(float, float) noexcept, const std::complex<float>, true>();
+ test_is_nothrow_applicable_from_function<double(float, float) noexcept, const std::complex<float>&, true>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::complex<float>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::complex<float>&, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::complex<float>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::complex<float>&, true>();
+
+ test_is_nothrow_applicable_from_function<double(double, double) noexcept, std::complex<double>, true>();
+ test_is_nothrow_applicable_from_function<double&(double&, double&) noexcept, std::complex<double>&, true>();
+ test_is_nothrow_applicable_from_function<void(double, double) noexcept, const std::complex<double>, true>();
+ test_is_nothrow_applicable_from_function<double(double, double) noexcept, const std::complex<double>&, true>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::complex<double>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::complex<double>&, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::complex<double>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::complex<double>&, true>();
+
+ test_is_nothrow_applicable_from_function<long double(long double, long double) noexcept,
+ std::complex<long double>,
+ true>();
+ test_is_nothrow_applicable_from_function<long double&(long double&, long double&) noexcept,
+ std::complex<long double>&,
+ true>();
+ test_is_nothrow_applicable_from_function<void(long double, long double) noexcept,
+ const std::complex<long double>,
+ true>();
+ test_is_nothrow_applicable_from_function<double(long double, long double) noexcept,
+ const std::complex<long double>&,
+ true>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::complex<long double>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::complex<long double>&, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::complex<long double>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::complex<long double>&, true>();
+
+ // test subrange
+ // Exception specifications may be different among implementations, see [res.on.exception.handling]/5.
+ using copyable_subrange = std::ranges::subrange<int*>;
+ constexpr bool can_nothrow_get_copyable_subrange_lv =
+ noexcept((void)std::get<0>(std::declval<const copyable_subrange&>()),
+ (void)std::get<1>(std::declval<const copyable_subrange&>()));
+ constexpr bool can_nothrow_get_copyable_subrange_rv = noexcept(
+ (void)std::get<0>(std::declval<copyable_subrange>()), (void)std::get<1>(std::declval<copyable_subrange>()));
+
+ test_is_nothrow_applicable_from_function<void(int*, int*) noexcept,
+ copyable_subrange,
+ can_nothrow_get_copyable_subrange_rv>();
+ test_is_nothrow_applicable_from_function<long(int*, int*) noexcept,
+ copyable_subrange&,
+ can_nothrow_get_copyable_subrange_lv>();
+ test_is_nothrow_applicable_from_function<int*&(int*, int*) noexcept,
+ const copyable_subrange,
+ can_nothrow_get_copyable_subrange_lv>();
+ test_is_nothrow_applicable_from_function<int* && (int*, int*) noexcept,
+ const copyable_subrange&,
+ can_nothrow_get_copyable_subrange_lv>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, copyable_subrange, can_nothrow_get_copyable_subrange_rv>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, copyable_subrange&, can_nothrow_get_copyable_subrange_lv>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const copyable_subrange, can_nothrow_get_copyable_subrange_lv>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const copyable_subrange&, can_nothrow_get_copyable_subrange_lv>();
+
+ using move_only_counted_iter = std::counted_iterator<cpp20_input_iterator<int*>>;
+ using move_only_subrange = std::ranges::subrange<move_only_counted_iter, std::default_sentinel_t>;
+ constexpr bool can_nothrow_get_move_only_subrange_rv = noexcept(
+ (void)std::get<0>(std::declval<move_only_subrange>()), (void)std::get<1>(std::declval<move_only_subrange>()));
+
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&&, std::default_sentinel_t),
+ move_only_subrange,
+ can_nothrow_get_move_only_subrange_rv>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, move_only_subrange, can_nothrow_get_move_only_subrange_rv>();
+
+ // test tuple
+ test_is_nothrow_applicable_from_function<int() noexcept, std::tuple<>, true>();
+ test_is_nothrow_applicable_from_function<char&() noexcept, std::tuple<>&, true>();
+ test_is_nothrow_applicable_from_function<long && () noexcept, const std::tuple<>, true>();
+ test_is_nothrow_applicable_from_function<void() noexcept, const std::tuple<>&, true>();
+
+ test_is_nothrow_applicable_from_function<int(long, int) noexcept, std::tuple<int, long>, true>();
+ test_is_nothrow_applicable_from_function<int&(long, int) noexcept, std::tuple<int, long>&, true>();
+ test_is_nothrow_applicable_from_function<const int && (long, int) noexcept, const std::tuple<int, long>, true>();
+ test_is_nothrow_applicable_from_function<void(long, int) noexcept, const std::tuple<int, long>&, true>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::tuple<>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::tuple<long>&, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::tuple<int, long>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::tuple<int, double, long>&, true>();
+
+ // test pair
+ test_is_nothrow_applicable_from_function<int(long, int) noexcept, std::pair<int, long>, true>();
+ test_is_nothrow_applicable_from_function<int&(long, int) noexcept, std::pair<int, long>&, true>();
+ test_is_nothrow_applicable_from_function<const int && (long, int) noexcept, const std::pair<int, long>, true>();
+ test_is_nothrow_applicable_from_function<void(long, int) noexcept, const std::pair<int, long>&, true>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::pair<char, wchar_t>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, std::pair<float, long>&, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::pair<int, long>, true>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const std::pair<int, double>&, true>();
+}
+
+void test_potentially_throwing() {
+ // test array
+ test_is_nothrow_applicable_from_function<int(), std::array<int, 0>, false>();
+ test_is_nothrow_applicable_from_function<int(), std::array<long, 0>&, false>();
+ test_is_nothrow_applicable_from_function<int(), const std::array<char, 0>, false>();
+ test_is_nothrow_applicable_from_function<int(), const std::array<std::array<int, 1>, 0>&, false>();
+
+ test_is_nothrow_applicable_from_function<int(long), std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<int&(int), std::array<long, 1>&, false>();
+ test_is_nothrow_applicable_from_function<const int && (float), const std::array<double, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(double), const std::array<char, 1>&, false>();
+
+ test_is_nothrow_applicable_from_function<int(long, int), std::array<int, 2>, false>();
+ test_is_nothrow_applicable_from_function<int&(long, int), std::array<int, 2>&, false>();
+ test_is_nothrow_applicable_from_function<const int && (long, int), const std::array<int, 2>, false>();
+ test_is_nothrow_applicable_from_function<void(long, int), const std::array<int, 2>&, false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, std::array<int, 0>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, std::array<int, 1>&, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::array<int, 2>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::array<int, 3>&, false>();
+
+ // test complex
+ test_is_nothrow_applicable_from_function<float(float, float), std::complex<float>, false>();
+ test_is_nothrow_applicable_from_function<float(float&, float&), std::complex<float>&, false>();
+ test_is_nothrow_applicable_from_function<void(float, float), const std::complex<float>, false>();
+ test_is_nothrow_applicable_from_function<double(float, float), const std::complex<float>&, false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, std::complex<float>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, std::complex<float>&, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::complex<float>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::complex<float>&, false>();
+
+ test_is_nothrow_applicable_from_function<double(double, double), std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<double&(double&, double&), std::complex<double>&, false>();
+ test_is_nothrow_applicable_from_function<void(double, double), const std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<double(double, double), std::complex<double>&, false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, std::complex<double>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, std::complex<double>&, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::complex<double>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::complex<double>&, false>();
+
+ test_is_nothrow_applicable_from_function<long double(long double, long double), std::complex<long double>, false>();
+ test_is_nothrow_applicable_from_function<long double&(long double&, long double&),
+ std::complex<long double>&,
+ false>();
+ test_is_nothrow_applicable_from_function<void(long double, long double), const std::complex<long double>, false>();
+ test_is_nothrow_applicable_from_function<double(long double, long double), const std::complex<long double>&, false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, std::complex<long double>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, std::complex<long double>&, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::complex<long double>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::complex<long double>&, false>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+ test_is_nothrow_applicable_from_function<void(int*, int*), copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<long(int*, int*), copyable_subrange&, false>();
+ test_is_nothrow_applicable_from_function<int*&(int*, int*), const copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<int* && (int*, int*), const copyable_subrange&, false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, copyable_subrange, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, copyable_subrange&, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const copyable_subrange, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const copyable_subrange&, false>();
+
+ using move_only_counted_iter = std::counted_iterator<cpp20_input_iterator<int*>>;
+ using move_only_subrange = std::ranges::subrange<move_only_counted_iter, std::default_sentinel_t>;
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&&, std::default_sentinel_t),
+ move_only_subrange,
+ false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, move_only_subrange, false>();
+
+ // test tuple
+ test_is_nothrow_applicable_from_function<int(), std::tuple<>, false>();
+ test_is_nothrow_applicable_from_function<char&(), std::tuple<>&, false>();
+ test_is_nothrow_applicable_from_function<long && (), const std::tuple<>, false>();
+ test_is_nothrow_applicable_from_function<void(), const std::tuple<>&, false>();
+
+ test_is_nothrow_applicable_from_function<int(long, int), std::tuple<int, long>, false>();
+ test_is_nothrow_applicable_from_function<int&(long, int), std::tuple<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<const int && (long, int), const std::tuple<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(long, int), const std::tuple<int, long>&, false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, std::tuple<>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, std::tuple<long>&, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::tuple<int, long>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::tuple<int, double, long>&, false>();
+
+ // test pair
+ test_is_nothrow_applicable_from_function<int(long, int), std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<int&(long, int), std::pair<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<const int && (long, int), const std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(long, int), const std::pair<int, long>&, false>();
+
+ test_is_nothrow_applicable<ConstCallable<bool>, std::pair<char, wchar_t>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, std::pair<float, long>&, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::pair<int, long>, false>();
+ test_is_nothrow_applicable<ConstCallable<bool>, const std::pair<int, double>&, false>();
+}
+
+void test_volatile() {
+ // test array
+ test_is_nothrow_applicable_from_function<void(int), volatile std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int), volatile std::array<int, 1>&, false>();
+ test_is_nothrow_applicable_from_function<void(int), const volatile std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int), const volatile std::array<int, 1>&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, volatile std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, volatile std::array<int, 1>&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const volatile std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const volatile std::array<int, 1>&, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::array<int, 1>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::array<int, 1>&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::array<int, 1>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::array<int, 1>&, false>();
+
+ // test complex
+ test_is_nothrow_applicable_from_function<void(double, double), volatile std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double, double), volatile std::complex<double>&, false>();
+ test_is_nothrow_applicable_from_function<void(double, double), const volatile std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double, double), const volatile std::complex<double>&, false>();
+ test_is_nothrow_applicable_from_function<void(double, double) noexcept, volatile std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double, double) noexcept, volatile std::complex<double>&, false>();
+ test_is_nothrow_applicable_from_function<void(double, double) noexcept, const volatile std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double, double) noexcept,
+ const volatile std::complex<double>&,
+ false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::complex<double>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::complex<double>&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::complex<double>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::complex<double>&, false>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_is_nothrow_applicable_from_function<void(int*, int*), volatile copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(int*, int*), volatile copyable_subrange&, false>();
+ test_is_nothrow_applicable_from_function<void(int*, int*), const volatile copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(int*, int*), const volatile copyable_subrange&, false>();
+ test_is_nothrow_applicable_from_function<void(int*, int*) noexcept, volatile copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(int*, int*) noexcept, volatile copyable_subrange&, false>();
+ test_is_nothrow_applicable_from_function<void(int*, int*) noexcept, const volatile copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(int*, int*) noexcept, const volatile copyable_subrange&, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile copyable_subrange, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile copyable_subrange&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile copyable_subrange, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile copyable_subrange&, false>();
+
+ // test tuple
+ test_is_nothrow_applicable_from_function<void(int, char*, double), volatile std::tuple<int, char*, double>, false>();
+ test_is_nothrow_applicable_from_function<void(int, char*, double), volatile std::tuple<int, char*, double>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, char*, double),
+ const volatile std::tuple<int, char*, double>,
+ false>();
+ test_is_nothrow_applicable_from_function<void(int, char*, double),
+ const volatile std::tuple<int, char*, double>&,
+ false>();
+ test_is_nothrow_applicable_from_function<void(int, char*, double) noexcept,
+ volatile std::tuple<int, char*, double>,
+ false>();
+ test_is_nothrow_applicable_from_function<void(int, char*, double) noexcept,
+ volatile std::tuple<int, char*, double>&,
+ false>();
+ test_is_nothrow_applicable_from_function<void(int, char*, double) noexcept,
+ const volatile std::tuple<int, char*, double>,
+ false>();
+ test_is_nothrow_applicable_from_function<void(int, char*, double) noexcept,
+ const volatile std::tuple<int, char*, double>&,
+ false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::tuple<int, char*, double>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::tuple<int, char*, double>&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::tuple<int, char*, double>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::tuple<int, char*, double>&, false>();
+
+ // test pair
+ test_is_nothrow_applicable_from_function<void(int, long), volatile std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long), volatile std::pair<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, long), const volatile std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long), const volatile std::pair<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, volatile std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, volatile std::pair<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, const volatile std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, const volatile std::pair<int, long>&, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::pair<int, long>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile std::pair<int, long>&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::pair<int, long>, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile std::pair<int, long>&, false>();
+}
+
+void test_invalid_nontuple_types() {
+ // test void
+ test_is_nothrow_applicable_from_function<void(), void, false>();
+ test_is_nothrow_applicable_from_function<void(), const void, false>();
+ test_is_nothrow_applicable_from_function<void(), volatile void, false>();
+ test_is_nothrow_applicable_from_function<void(), const volatile void, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, void, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, const void, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, volatile void, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, const volatile void, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const void, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, volatile void, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const volatile void, false>();
+
+ // test function
+ test_is_nothrow_applicable_from_function<void(void (&)()), void(), false>();
+ test_is_nothrow_applicable_from_function<void(void (&)()), void (&)(), false>();
+ test_is_nothrow_applicable_from_function<void(void (&)()) noexcept, void(), false>();
+ test_is_nothrow_applicable_from_function<void(void (&)()) noexcept, void (&)(), false>();
+ test_is_nothrow_applicable_from_function<void(void (&)()), void() const & noexcept, false>();
+ test_is_nothrow_applicable_from_function<void(void (&)()) noexcept, void() const & noexcept, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void(), false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void (&)(), false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void() const & noexcept, false>();
+
+ // test scalar
+ test_is_nothrow_applicable_from_function<void(int), int, false>();
+ test_is_nothrow_applicable_from_function<void(int), int&, false>();
+ test_is_nothrow_applicable_from_function<void(int), const int, false>();
+ test_is_nothrow_applicable_from_function<void(int), const int&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, int, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, int&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const int, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const int&, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, int, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, int&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const int, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const int&, false>();
+
+ test_is_nothrow_applicable_from_function<void(void*), void*, false>();
+ test_is_nothrow_applicable_from_function<void(void*), void*&, false>();
+ test_is_nothrow_applicable_from_function<void(void*), void* const, false>();
+ test_is_nothrow_applicable_from_function<void(void*), void* const&, false>();
+ test_is_nothrow_applicable_from_function<void(void*) noexcept, void*, false>();
+ test_is_nothrow_applicable_from_function<void(void*) noexcept, void*&, false>();
+ test_is_nothrow_applicable_from_function<void(void*) noexcept, void* const, false>();
+ test_is_nothrow_applicable_from_function<void(void*) noexcept, void* const&, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void*, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void*&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void* const, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, void* const&, false>();
+
+ // test plain aggregate
+ test_is_nothrow_applicable_from_function<void(), empty_aggregate, false>();
+ test_is_nothrow_applicable_from_function<void(), empty_aggregate&, false>();
+ test_is_nothrow_applicable_from_function<void(), const empty_aggregate, false>();
+ test_is_nothrow_applicable_from_function<void(), const empty_aggregate&, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, empty_aggregate, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, empty_aggregate&, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, const empty_aggregate, false>();
+ test_is_nothrow_applicable_from_function<void() noexcept, const empty_aggregate&, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, empty_aggregate, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, empty_aggregate&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const empty_aggregate, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const empty_aggregate&, false>();
+
+ // test std::get-able class
+ test_is_nothrow_applicable_from_function<void(int), derived_from_tuple_int, false>();
+ test_is_nothrow_applicable_from_function<void(int), derived_from_tuple_int&, false>();
+ test_is_nothrow_applicable_from_function<void(int), const derived_from_tuple_int, false>();
+ test_is_nothrow_applicable_from_function<void(int), const derived_from_tuple_int&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, derived_from_tuple_int, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, derived_from_tuple_int&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const derived_from_tuple_int, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const derived_from_tuple_int&, false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, derived_from_tuple_int, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, derived_from_tuple_int&, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const derived_from_tuple_int, false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const derived_from_tuple_int&, false>();
+
+ // test built-in array
+ test_is_nothrow_applicable_from_function<void(int), int[1], false>();
+ test_is_nothrow_applicable_from_function<void(int), int (&)[1], false>();
+ test_is_nothrow_applicable_from_function<void(int), const int[1], false>();
+ test_is_nothrow_applicable_from_function<void(int), const int (&)[1], false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, int[1], false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, int (&)[1], false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const int[1], false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const int (&)[1], false>();
+
+ test_is_nothrow_applicable<NoExceptCallable<bool>, int[1], false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, int (&)[1], false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const int[1], false>();
+ test_is_nothrow_applicable<NoExceptCallable<bool>, const int (&)[1], false>();
+}
+
+void test_invalid_invocations() {
+ // test array
+ test_is_nothrow_applicable<void, std::array<int, 0>, false>();
+ test_is_nothrow_applicable<void*, std::array<int, 1>, false>();
+ test_is_nothrow_applicable<int, std::array<int, 2>, false>();
+ test_is_nothrow_applicable<int&, std::array<int, 3>, false>();
+ test_is_nothrow_applicable<int(int, int, int, int) const & noexcept, std::array<int, 4>, false>();
+
+ test_is_nothrow_applicable_from_function<void(int), std::array<int, 0>, false>();
+ test_is_nothrow_applicable_from_function<void(int), std::array<int, 0>&, false>();
+ test_is_nothrow_applicable_from_function<void(int), const std::array<int, 0>, false>();
+ test_is_nothrow_applicable_from_function<void(int), const std::array<int, 0>&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, std::array<int, 0>, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, std::array<int, 0>&, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const std::array<int, 0>, false>();
+ test_is_nothrow_applicable_from_function<void(int) noexcept, const std::array<int, 0>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, long), std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long), std::array<int, 1>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, long), const std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long), const std::array<int, 1>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, std::array<int, 1>&, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, const std::array<int, 1>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long) noexcept, const std::array<int, 1>&, false>();
+
+ // test complex
+ test_is_nothrow_applicable<void, std::complex<float>, false>();
+ test_is_nothrow_applicable<void*, std::complex<float>, false>();
+ test_is_nothrow_applicable<int, std::complex<float>, false>();
+ test_is_nothrow_applicable<int&, std::complex<float>, false>();
+ test_is_nothrow_applicable<void(float, float) const & noexcept, std::complex<float>, false>();
+
+ test_is_nothrow_applicable<void, std::complex<double>, false>();
+ test_is_nothrow_applicable<void*, std::complex<double>, false>();
+ test_is_nothrow_applicable<int, std::complex<double>, false>();
+ test_is_nothrow_applicable<int&, std::complex<double>, false>();
+ test_is_nothrow_applicable<void(double, double) const & noexcept, std::complex<double>, false>();
+
+ test_is_nothrow_applicable<void, std::complex<long double>, false>();
+ test_is_nothrow_applicable<void*, std::complex<long double>, false>();
+ test_is_nothrow_applicable<int, std::complex<long double>, false>();
+ test_is_nothrow_applicable<int&, std::complex<long double>, false>();
+ test_is_nothrow_applicable<void(long double, long double) const & noexcept, std::complex<long double>, false>();
+
+ test_is_nothrow_applicable_from_function<void(float), std::complex<float>, false>();
+ test_is_nothrow_applicable_from_function<void(float), std::complex<float>&, false>();
+ test_is_nothrow_applicable_from_function<void(float), const std::complex<float>, false>();
+ test_is_nothrow_applicable_from_function<void(float), const std::complex<float>&, false>();
+ test_is_nothrow_applicable_from_function<void(float) noexcept, std::complex<float>, false>();
+ test_is_nothrow_applicable_from_function<void(float) noexcept, std::complex<float>&, false>();
+ test_is_nothrow_applicable_from_function<void(float) noexcept, const std::complex<float>, false>();
+ test_is_nothrow_applicable_from_function<void(float) noexcept, const std::complex<float>&, false>();
+
+ test_is_nothrow_applicable_from_function<void(double), std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double), std::complex<double>&, false>();
+ test_is_nothrow_applicable_from_function<void(double), const std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double), const std::complex<double>&, false>();
+ test_is_nothrow_applicable_from_function<void(double) noexcept, std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double) noexcept, std::complex<double>&, false>();
+ test_is_nothrow_applicable_from_function<void(double) noexcept, const std::complex<double>, false>();
+ test_is_nothrow_applicable_from_function<void(double) noexcept, const std::complex<double>&, false>();
+
+ test_is_nothrow_applicable_from_function<void(long double), std::complex<long double>, false>();
+ test_is_nothrow_applicable_from_function<void(long double), std::complex<long double>&, false>();
+ test_is_nothrow_applicable_from_function<void(long double), const std::complex<long double>, false>();
+ test_is_nothrow_applicable_from_function<void(long double), const std::complex<long double>&, false>();
+ test_is_nothrow_applicable_from_function<void(long double) noexcept, std::complex<long double>, false>();
+ test_is_nothrow_applicable_from_function<void(long double) noexcept, std::complex<long double>&, false>();
+ test_is_nothrow_applicable_from_function<void(long double) noexcept, const std::complex<long double>, false>();
+ test_is_nothrow_applicable_from_function<void(long double) noexcept, const std::complex<long double>&, false>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_is_nothrow_applicable<void, copyable_subrange, false>();
+ test_is_nothrow_applicable<void*, copyable_subrange, false>();
+ test_is_nothrow_applicable<int, copyable_subrange, false>();
+ test_is_nothrow_applicable<int&, copyable_subrange, false>();
+
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t), copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t), copyable_subrange&, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t), const copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t), const copyable_subrange&, false>();
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t) noexcept, copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t) noexcept, copyable_subrange&, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t) noexcept, const copyable_subrange, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t) noexcept, const copyable_subrange&, false>();
+
+ using move_only_counted_iter = std::counted_iterator<cpp20_input_iterator<int*>>;
+ using move_only_subrange = std::ranges::subrange<move_only_counted_iter, std::default_sentinel_t>;
+
+ test_is_nothrow_applicable<void, move_only_subrange, false>();
+ test_is_nothrow_applicable<void*, move_only_subrange, false>();
+ test_is_nothrow_applicable<int, move_only_subrange, false>();
+ test_is_nothrow_applicable<int&, move_only_subrange, false>();
+
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ move_only_subrange&,
+ false>();
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ const move_only_subrange,
+ false>();
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ const move_only_subrange&,
+ false>();
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ move_only_subrange&,
+ false>();
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ const move_only_subrange,
+ false>();
+ test_is_nothrow_applicable_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ const move_only_subrange&,
+ false>();
+
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t), move_only_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t), move_only_subrange&, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t), const move_only_subrange, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t), const move_only_subrange&, false>();
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t) noexcept, move_only_subrange, false>();
+ test_is_nothrow_applicable_from_function<void(std::default_sentinel_t) noexcept, move_only_subrange&, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t) noexcept, const move_only_subrange, false>();
+ test_is_nothrow_applicable_from_function<int(std::default_sentinel_t) noexcept, const move_only_subrange&, false>();
+
+ // test tuple
+ test_is_nothrow_applicable<void, std::tuple<>, false>();
+ test_is_nothrow_applicable<void*, std::tuple<>, false>();
+ test_is_nothrow_applicable<int, std::tuple<int>, false>();
+ test_is_nothrow_applicable<int&, std::tuple<int>, false>();
+ test_is_nothrow_applicable<int() const&, std::tuple<>, false>();
+ test_is_nothrow_applicable<int() const & noexcept, std::tuple<>, false>();
+
+ test_is_nothrow_applicable_from_function<int(), std::tuple<int>, false>();
+ test_is_nothrow_applicable_from_function<int(), std::tuple<int>&, false>();
+ test_is_nothrow_applicable_from_function<int(), const std::tuple<int>, false>();
+ test_is_nothrow_applicable_from_function<int(), const std::tuple<int>&, false>();
+ test_is_nothrow_applicable_from_function<int() noexcept, std::tuple<int>, false>();
+ test_is_nothrow_applicable_from_function<int() noexcept, std::tuple<int>&, false>();
+ test_is_nothrow_applicable_from_function<int() noexcept, const std::tuple<int>, false>();
+ test_is_nothrow_applicable_from_function<int() noexcept, const std::tuple<int>&, false>();
+
+ // test pair
+ test_is_nothrow_applicable<void, std::pair<int, long>, false>();
+ test_is_nothrow_applicable<void*, std::pair<int, long>, false>();
+ test_is_nothrow_applicable<int, std::pair<int, long>, false>();
+ test_is_nothrow_applicable<int&, std::pair<int, long>, false>();
+
+ test_is_nothrow_applicable<int(int, long) const&, std::pair<int, long>, false>();
+ test_is_nothrow_applicable<int(int, long) const & noexcept, std::pair<int, long>, false>();
+
+ test_is_nothrow_applicable_from_function<int(), std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long, long long), std::pair<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<int&(int), const std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<long&(int&, long&), const std::pair<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<int() noexcept, std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<void(int, long, long long) noexcept, std::pair<int, long>&, false>();
+ test_is_nothrow_applicable_from_function<int&(int) noexcept, const std::pair<int, long>, false>();
+ test_is_nothrow_applicable_from_function<long&(int&, long&) noexcept, const std::pair<int, long>&, false>();
+}
diff --git a/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/apply_result.compile.pass.cpp b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/apply_result.compile.pass.cpp
new file mode 100644
index 0000000000000..21ec35aba8a0a
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.trans/meta.trans.other/apply_result.compile.pass.cpp
@@ -0,0 +1,629 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <type_traits>
+
+// template<class Fn, class Tuple> struct apply_result;
+
+// template<class Fn, class Tuple>
+// using apply_result_t = typename apply_result<T, U>::type;
+
+#include <cassert>
+#include <cstddef>
+#include <array>
+#include <complex>
+#include <ranges>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "callable_types.h"
+#include "test_iterators.h"
+
+struct empty_aggregate {};
+
+struct derived_from_tuple_int : std::tuple<int> {};
+
+template <>
+struct std::tuple_size<derived_from_tuple_int> : std::integral_constant<std::size_t, 1> {};
+
+template <std::size_t I>
+ requires(I < 1)
+struct std::tuple_element<I, derived_from_tuple_int> {
+ using type = std::tuple_element_t<I, std::tuple<int>>;
+};
+
+template <class Fn, class Tuple>
+concept apply_result_has_member_type = requires { typename std::apply_result<Fn, Tuple>::type; };
+
+template <class Fn, class Tuple>
+concept apply_result_t_is_valid = requires { typename std::apply_result_t<Fn, Tuple>; };
+
+template <class Fn, class Tuple, class Expected>
+void test_valid_apply_result() {
+ static_assert(apply_result_has_member_type<Fn, Tuple>);
+ static_assert(apply_result_t_is_valid<Fn, Tuple>);
+ static_assert(std::is_same_v<typename std::apply_result<Fn, Tuple>::type, Expected>);
+ static_assert(std::is_same_v<std::apply_result_t<Fn, Tuple>, Expected>);
+}
+
+template <class Func, class Tuple, class Expected>
+void test_valid_apply_result_from_function() {
+ static_assert(std::is_function_v<Func>);
+
+ test_valid_apply_result<Func, Tuple, Expected>();
+ test_valid_apply_result<Func&, Tuple, Expected>();
+
+ test_valid_apply_result<Func*, Tuple, Expected>();
+ test_valid_apply_result<Func*&, Tuple, Expected>();
+ test_valid_apply_result<Func* const, Tuple, Expected>();
+ test_valid_apply_result<Func* const&, Tuple, Expected>();
+ test_valid_apply_result<Func* volatile, Tuple, Expected>();
+ test_valid_apply_result<Func* volatile&, Tuple, Expected>();
+ test_valid_apply_result<Func* const volatile, Tuple, Expected>();
+ test_valid_apply_result<Func* const volatile&, Tuple, Expected>();
+}
+
+template <class Fn, class Tuple>
+void test_invalid_apply_result() {
+ static_assert(!apply_result_has_member_type<Fn, Tuple>);
+ static_assert(!apply_result_t_is_valid<Fn, Tuple>);
+}
+
+template <class Func, class Tuple>
+void test_invalid_apply_result_from_function() {
+ static_assert(std::is_function_v<Func>);
+
+ test_invalid_apply_result<Func, Tuple>();
+ test_invalid_apply_result<Func&, Tuple>();
+
+ test_invalid_apply_result<Func*, Tuple>();
+ test_invalid_apply_result<Func*&, Tuple>();
+ test_invalid_apply_result<Func* const, Tuple>();
+ test_invalid_apply_result<Func* const&, Tuple>();
+ test_invalid_apply_result<Func* volatile, Tuple>();
+ test_invalid_apply_result<Func* volatile&, Tuple>();
+ test_invalid_apply_result<Func* const volatile, Tuple>();
+ test_invalid_apply_result<Func* const volatile&, Tuple>();
+}
+
+void test_valid() {
+ // test array
+ test_valid_apply_result_from_function<int(), std::array<int, 0>, int>();
+ test_valid_apply_result_from_function<int(), std::array<long, 0>&, int>();
+ test_valid_apply_result_from_function<int(), const std::array<char, 0>, int>();
+ test_valid_apply_result_from_function<int(), const std::array<std::array<int, 1>, 0>&, int>();
+ test_valid_apply_result_from_function<int() noexcept, std::array<int, 0>, int>();
+ test_valid_apply_result_from_function<int() noexcept, std::array<long, 0>&, int>();
+ test_valid_apply_result_from_function<int() noexcept, const std::array<char, 0>, int>();
+ test_valid_apply_result_from_function<int() noexcept, const std::array<std::array<int, 1>, 0>&, int>();
+
+ test_valid_apply_result_from_function<int(long), std::array<int, 1>, int>();
+ test_valid_apply_result_from_function<int&(int), std::array<long, 1>&, int&>();
+ test_valid_apply_result_from_function<const int && (float), const std::array<double, 1>, const int&&>();
+ test_valid_apply_result_from_function<void(double), const std::array<char, 1>&, void>();
+ test_valid_apply_result_from_function<int(long) noexcept, std::array<int, 1>, int>();
+ test_valid_apply_result_from_function<int&(int) noexcept, std::array<long, 1>&, int&>();
+ test_valid_apply_result_from_function<const int && (float) noexcept, const std::array<double, 1>, const int&&>();
+ test_valid_apply_result_from_function<void(double) noexcept, const std::array<char, 1>&, void>();
+
+ test_valid_apply_result_from_function<int(long, int), std::array<int, 2>, int>();
+ test_valid_apply_result_from_function<int&(long, int), std::array<int, 2>&, int&>();
+ test_valid_apply_result_from_function<const int && (long, int), const std::array<int, 2>, const int&&>();
+ test_valid_apply_result_from_function<void(long, int), const std::array<int, 2>&, void>();
+ test_valid_apply_result_from_function<int(long, int) noexcept, std::array<int, 2>, int>();
+ test_valid_apply_result_from_function<int&(long, int) noexcept, std::array<int, 2>&, int&>();
+ test_valid_apply_result_from_function<const int && (long, int) noexcept, const std::array<int, 2>, const int&&>();
+ test_valid_apply_result_from_function<void(long, int) noexcept, const std::array<int, 2>&, void>();
+
+ test_valid_apply_result<ConstCallable<bool>, std::array<int, 0>, bool>();
+ test_valid_apply_result<ConstCallable<signed char>, std::array<int, 1>&, signed char>();
+ test_valid_apply_result<ConstCallable<short>, const std::array<int, 2>, short>();
+ test_valid_apply_result<ConstCallable<int>, const std::array<int, 3>&, int>();
+
+ test_valid_apply_result<NoExceptCallable<bool>, std::array<int, 0>, bool>();
+ test_valid_apply_result<NoExceptCallable<unsigned char>, std::array<int, 1>&, unsigned char>();
+ test_valid_apply_result<NoExceptCallable<unsigned short>, const std::array<int, 2>, unsigned short>();
+ test_valid_apply_result<NoExceptCallable<unsigned int>, const std::array<int, 3>&, unsigned int>();
+
+ // test complex
+ test_valid_apply_result_from_function<float(float, float), std::complex<float>, float>();
+ test_valid_apply_result_from_function<float(float&, float&), std::complex<float>&, float>();
+ test_valid_apply_result_from_function<void(float, float), const std::complex<float>, void>();
+ test_valid_apply_result_from_function<double(float, float), const std::complex<float>&, double>();
+ test_valid_apply_result_from_function<float(float, float) noexcept, std::complex<float>, float>();
+ test_valid_apply_result_from_function<float(float&, float&) noexcept, std::complex<float>&, float>();
+ test_valid_apply_result_from_function<void(float, float) noexcept, const std::complex<float>, void>();
+ test_valid_apply_result_from_function<double(float, float) noexcept, const std::complex<float>&, double>();
+
+ test_valid_apply_result<ConstCallable<bool>, std::complex<float>, bool>();
+ test_valid_apply_result<ConstCallable<signed char>, std::complex<float>&, signed char>();
+ test_valid_apply_result<ConstCallable<int>, const std::complex<float>, int>();
+ test_valid_apply_result<ConstCallable<short>, const std::complex<float>&, short>();
+
+ test_valid_apply_result<NoExceptCallable<unsigned long>, std::complex<float>, unsigned long>();
+ test_valid_apply_result<NoExceptCallable<bool>, std::complex<float>&, bool>();
+ test_valid_apply_result<NoExceptCallable<unsigned int>, const std::complex<float>, unsigned int>();
+ test_valid_apply_result<NoExceptCallable<unsigned short>, const std::complex<float>&, unsigned short>();
+
+ test_valid_apply_result_from_function<double(double, double), std::complex<double>, double>();
+ test_valid_apply_result_from_function<double&(double&, double&), std::complex<double>&, double&>();
+ test_valid_apply_result_from_function<void(double, double), const std::complex<double>, void>();
+ test_valid_apply_result_from_function<double(double, double), const std::complex<double>&, double>();
+ test_valid_apply_result_from_function<double(double, double) noexcept, std::complex<double>, double>();
+ test_valid_apply_result_from_function<double&(double&, double&) noexcept, std::complex<double>&, double&>();
+ test_valid_apply_result_from_function<void(double, double) noexcept, const std::complex<double>, void>();
+ test_valid_apply_result_from_function<double(double, double) noexcept, const std::complex<double>&, double>();
+
+ test_valid_apply_result<ConstCallable<bool>, std::complex<double>, bool>();
+ test_valid_apply_result<ConstCallable<signed char>, std::complex<double>&, signed char>();
+ test_valid_apply_result<ConstCallable<short>, const std::complex<double>, short>();
+ test_valid_apply_result<ConstCallable<int>, const std::complex<double>&, int>();
+
+ test_valid_apply_result<NoExceptCallable<unsigned short>, std::complex<double>, unsigned short>();
+ test_valid_apply_result<NoExceptCallable<unsigned long>, std::complex<double>&, unsigned long>();
+ test_valid_apply_result<NoExceptCallable<bool>, const std::complex<double>, bool>();
+ test_valid_apply_result<NoExceptCallable<unsigned char>, const std::complex<double>&, unsigned char>();
+
+ test_valid_apply_result_from_function<long double(long double, long double),
+ std::complex<long double>,
+ long double>();
+ test_valid_apply_result_from_function<long double&(long double&, long double&),
+ std::complex<long double>&,
+ long double&>();
+ test_valid_apply_result_from_function<void(long double, long double), const std::complex<long double>, void>();
+ test_valid_apply_result_from_function<double(long double, long double), const std::complex<long double>&, double>();
+ test_valid_apply_result_from_function<long double(long double, long double) noexcept,
+ std::complex<long double>,
+ long double>();
+ test_valid_apply_result_from_function<long double&(long double&, long double&) noexcept,
+ std::complex<long double>&,
+ long double&>();
+ test_valid_apply_result_from_function<void(long double, long double) noexcept,
+ const std::complex<long double>,
+ void>();
+ test_valid_apply_result_from_function<double(long double, long double) noexcept,
+ const std::complex<long double>&,
+ double>();
+
+ test_valid_apply_result<ConstCallable<bool>, std::complex<long double>, bool>();
+ test_valid_apply_result<ConstCallable<signed char>, std::complex<long double>&, signed char>();
+ test_valid_apply_result<ConstCallable<short>, const std::complex<long double>, short>();
+ test_valid_apply_result<ConstCallable<int>, const std::complex<long double>&, int>();
+
+ test_valid_apply_result<NoExceptCallable<bool>, std::complex<long double>, bool>();
+ test_valid_apply_result<NoExceptCallable<unsigned char>, std::complex<long double>&, unsigned char>();
+ test_valid_apply_result<NoExceptCallable<unsigned short>, const std::complex<long double>, unsigned short>();
+ test_valid_apply_result<NoExceptCallable<unsigned int>, const std::complex<long double>&, unsigned int>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_valid_apply_result_from_function<void(int*, int*), copyable_subrange, void>();
+ test_valid_apply_result_from_function<long(int*, int*), copyable_subrange&, long>();
+ test_valid_apply_result_from_function<int*&(int*, int*), const copyable_subrange, int*&>();
+ test_valid_apply_result_from_function<int* && (int*, int*), const copyable_subrange&, int*&&>();
+ test_valid_apply_result_from_function<void(int*, int*) noexcept, copyable_subrange, void>();
+ test_valid_apply_result_from_function<long(int*, int*) noexcept, copyable_subrange&, long>();
+ test_valid_apply_result_from_function<int*&(int*, int*) noexcept, const copyable_subrange, int*&>();
+ test_valid_apply_result_from_function<int* && (int*, int*) noexcept, const copyable_subrange&, int*&&>();
+
+ test_valid_apply_result<ConstCallable<bool>, copyable_subrange, bool>();
+ test_valid_apply_result<ConstCallable<unsigned char>, copyable_subrange&, unsigned char>();
+ test_valid_apply_result<ConstCallable<short>, const copyable_subrange, short>();
+ test_valid_apply_result<ConstCallable<unsigned long>, const copyable_subrange&, unsigned long>();
+
+ test_valid_apply_result<NoExceptCallable<signed char>, copyable_subrange, signed char>();
+ test_valid_apply_result<NoExceptCallable<unsigned int>, copyable_subrange&, unsigned int>();
+ test_valid_apply_result<NoExceptCallable<long long>, const copyable_subrange, long long>();
+ test_valid_apply_result<NoExceptCallable<unsigned short>, const copyable_subrange&, unsigned short>();
+
+ using move_only_counted_iter = std::counted_iterator<cpp20_input_iterator<int*>>;
+ using move_only_subrange = std::ranges::subrange<move_only_counted_iter, std::default_sentinel_t>;
+
+ test_valid_apply_result_from_function<void(move_only_counted_iter&&, std::default_sentinel_t),
+ move_only_subrange,
+ void>();
+ test_valid_apply_result_from_function<void*(move_only_counted_iter&&, std::default_sentinel_t) noexcept,
+ move_only_subrange,
+ void*>();
+
+ test_valid_apply_result<ConstCallable<long long>, move_only_subrange, long long>();
+
+ test_valid_apply_result<NoExceptCallable<unsigned long long>, move_only_subrange, unsigned long long>();
+
+ // test tuple
+ test_valid_apply_result_from_function<int(), std::tuple<>, int>();
+ test_valid_apply_result_from_function<char&(), std::tuple<>&, char&>();
+ test_valid_apply_result_from_function<long && (), const std::tuple<>, long&&>();
+ test_valid_apply_result_from_function<void(), const std::tuple<>&, void>();
+ test_valid_apply_result_from_function<int() noexcept, std::tuple<>, int>();
+ test_valid_apply_result_from_function<char&() noexcept, std::tuple<>&, char&>();
+ test_valid_apply_result_from_function<long && () noexcept, const std::tuple<>, long&&>();
+ test_valid_apply_result_from_function<void() noexcept, const std::tuple<>&, void>();
+
+ test_valid_apply_result_from_function<int(long, int), std::tuple<int, long>, int>();
+ test_valid_apply_result_from_function<int&(long, int), std::tuple<int, long>&, int&>();
+ test_valid_apply_result_from_function<const int && (long, int), const std::tuple<int, long>, const int&&>();
+ test_valid_apply_result_from_function<void(long, int), const std::tuple<int, long>&, void>();
+ test_valid_apply_result_from_function<int(long, int) noexcept, std::tuple<int, long>, int>();
+ test_valid_apply_result_from_function<int&(long, int) noexcept, std::tuple<int, long>&, int&>();
+ test_valid_apply_result_from_function<const int && (long, int) noexcept, const std::tuple<int, long>, const int&&>();
+ test_valid_apply_result_from_function<void(long, int) noexcept, const std::tuple<int, long>&, void>();
+
+ test_valid_apply_result<ConstCallable<unsigned long long>, std::tuple<>, unsigned long long>();
+ test_valid_apply_result<ConstCallable<unsigned long>, std::tuple<long>&, unsigned long>();
+ test_valid_apply_result<ConstCallable<unsigned int>, const std::tuple<int, long>, unsigned int>();
+ test_valid_apply_result<ConstCallable<unsigned short>, const std::tuple<int, double, long>&, unsigned short>();
+
+ test_valid_apply_result<NoExceptCallable<long long>, std::tuple<>, long long>();
+ test_valid_apply_result<NoExceptCallable<long>, std::tuple<long>&, long>();
+ test_valid_apply_result<NoExceptCallable<int>, const std::tuple<int, long>, int>();
+ test_valid_apply_result<NoExceptCallable<short>, const std::tuple<int, double, long>&, short>();
+
+ // test pair
+ test_valid_apply_result_from_function<int(long, int), std::pair<int, long>, int>();
+ test_valid_apply_result_from_function<int&(long, int), std::pair<int, long>&, int&>();
+ test_valid_apply_result_from_function<const int && (long, int), const std::pair<int, long>, const int&&>();
+ test_valid_apply_result_from_function<void(long, int), const std::pair<int, long>&, void>();
+ test_valid_apply_result_from_function<int(long, int) noexcept, std::pair<int, long>, int>();
+ test_valid_apply_result_from_function<int&(long, int) noexcept, std::pair<int, long>&, int&>();
+ test_valid_apply_result_from_function<const int && (long, int) noexcept, const std::pair<int, long>, const int&&>();
+ test_valid_apply_result_from_function<void(long, int) noexcept, const std::pair<int, long>&, void>();
+
+ test_valid_apply_result<ConstCallable<bool>, std::pair<char, wchar_t>, bool>();
+ test_valid_apply_result<ConstCallable<unsigned char>, std::pair<float, long>&, unsigned char>();
+ test_valid_apply_result<ConstCallable<unsigned int>, const std::pair<int, long>, unsigned int>();
+ test_valid_apply_result<ConstCallable<unsigned short>, const std::pair<int, double>&, unsigned short>();
+
+ test_valid_apply_result<NoExceptCallable<int>, std::pair<char, wchar_t>, int>();
+ test_valid_apply_result<NoExceptCallable<short>, std::pair<float, long>&, short>();
+ test_valid_apply_result<NoExceptCallable<long>, const std::pair<int, long>, long>();
+ test_valid_apply_result<NoExceptCallable<long long>, const std::pair<int, double>&, long long>();
+}
+
+void test_volatile() {
+ // test array
+ test_invalid_apply_result_from_function<void(int), volatile std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int), volatile std::array<int, 1>&>();
+ test_invalid_apply_result_from_function<void(int), const volatile std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int), const volatile std::array<int, 1>&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, volatile std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int) noexcept, volatile std::array<int, 1>&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const volatile std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const volatile std::array<int, 1>&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::array<int, 1>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::array<int, 1>&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::array<int, 1>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::array<int, 1>&>();
+
+ // test complex
+ test_invalid_apply_result_from_function<void(double, double), volatile std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double, double), volatile std::complex<double>&>();
+ test_invalid_apply_result_from_function<void(double, double), const volatile std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double, double), const volatile std::complex<double>&>();
+ test_invalid_apply_result_from_function<void(double, double) noexcept, volatile std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double, double) noexcept, volatile std::complex<double>&>();
+ test_invalid_apply_result_from_function<void(double, double) noexcept, const volatile std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double, double) noexcept, const volatile std::complex<double>&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::complex<double>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::complex<double>&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::complex<double>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::complex<double>&>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_invalid_apply_result_from_function<void(int*, int*), volatile copyable_subrange>();
+ test_invalid_apply_result_from_function<void(int*, int*), volatile copyable_subrange&>();
+ test_invalid_apply_result_from_function<void(int*, int*), const volatile copyable_subrange>();
+ test_invalid_apply_result_from_function<void(int*, int*), const volatile copyable_subrange&>();
+ test_invalid_apply_result_from_function<void(int*, int*) noexcept, volatile copyable_subrange>();
+ test_invalid_apply_result_from_function<void(int*, int*) noexcept, volatile copyable_subrange&>();
+ test_invalid_apply_result_from_function<void(int*, int*) noexcept, const volatile copyable_subrange>();
+ test_invalid_apply_result_from_function<void(int*, int*) noexcept, const volatile copyable_subrange&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile copyable_subrange>();
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile copyable_subrange&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile copyable_subrange>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile copyable_subrange&>();
+
+ // test tuple
+ test_invalid_apply_result_from_function<void(int, char*, double), volatile std::tuple<int, char*, double>>();
+ test_invalid_apply_result_from_function<void(int, char*, double), volatile std::tuple<int, char*, double>&>();
+ test_invalid_apply_result_from_function<void(int, char*, double), const volatile std::tuple<int, char*, double>>();
+ test_invalid_apply_result_from_function<void(int, char*, double), const volatile std::tuple<int, char*, double>&>();
+ test_invalid_apply_result_from_function<void(int, char*, double) noexcept, volatile std::tuple<int, char*, double>>();
+ test_invalid_apply_result_from_function<void(int, char*, double) noexcept,
+ volatile std::tuple<int, char*, double>&>();
+ test_invalid_apply_result_from_function<void(int, char*, double) noexcept,
+ const volatile std::tuple<int, char*, double>>();
+ test_invalid_apply_result_from_function<void(int, char*, double) noexcept,
+ const volatile std::tuple<int, char*, double>&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::tuple<int, char*, double>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::tuple<int, char*, double>&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::tuple<int, char*, double>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::tuple<int, char*, double>&>();
+
+ // test pair
+ test_invalid_apply_result_from_function<void(int, long), volatile std::pair<int, long>>();
+ test_invalid_apply_result_from_function<void(int, long), volatile std::pair<int, long>&>();
+ test_invalid_apply_result_from_function<void(int, long), const volatile std::pair<int, long>>();
+ test_invalid_apply_result_from_function<void(int, long), const volatile std::pair<int, long>&>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, volatile std::pair<int, long>>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, volatile std::pair<int, long>&>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, const volatile std::pair<int, long>>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, const volatile std::pair<int, long>&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::pair<int, long>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile std::pair<int, long>&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::pair<int, long>>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile std::pair<int, long>&>();
+}
+
+void test_invalid_nontuple_types() {
+ // test void
+ test_invalid_apply_result_from_function<void(), void>();
+ test_invalid_apply_result_from_function<void(), const void>();
+ test_invalid_apply_result_from_function<void(), volatile void>();
+ test_invalid_apply_result_from_function<void(), const volatile void>();
+ test_invalid_apply_result_from_function<void() noexcept, void>();
+ test_invalid_apply_result_from_function<void() noexcept, const void>();
+ test_invalid_apply_result_from_function<void() noexcept, volatile void>();
+ test_invalid_apply_result_from_function<void() noexcept, const volatile void>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, void>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const void>();
+ test_invalid_apply_result<NoExceptCallable<bool>, volatile void>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const volatile void>();
+
+ // test function
+ test_invalid_apply_result_from_function<void(void (&)()), void()>();
+ test_invalid_apply_result_from_function<void(void (&)()), void (&)()>();
+ test_invalid_apply_result_from_function<void(void (&)()) noexcept, void()>();
+ test_invalid_apply_result_from_function<void(void (&)()) noexcept, void (&)()>();
+ test_invalid_apply_result_from_function<void(void (&)()), void() const & noexcept>();
+ test_invalid_apply_result_from_function<void(void (&)()) noexcept, void() const & noexcept>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, void()>();
+ test_invalid_apply_result<NoExceptCallable<bool>, void (&)()>();
+ test_invalid_apply_result<NoExceptCallable<bool>, void() const & noexcept>();
+
+ // test scalar
+ test_invalid_apply_result_from_function<void(int), int>();
+ test_invalid_apply_result_from_function<void(int), int&>();
+ test_invalid_apply_result_from_function<void(int), const int>();
+ test_invalid_apply_result_from_function<void(int), const int&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, int>();
+ test_invalid_apply_result_from_function<void(int) noexcept, int&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const int>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const int&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, int>();
+ test_invalid_apply_result<NoExceptCallable<bool>, int&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const int>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const int&>();
+
+ test_invalid_apply_result_from_function<void(void*), void*>();
+ test_invalid_apply_result_from_function<void(void*), void*&>();
+ test_invalid_apply_result_from_function<void(void*), void* const>();
+ test_invalid_apply_result_from_function<void(void*), void* const&>();
+ test_invalid_apply_result_from_function<void(void*) noexcept, void*>();
+ test_invalid_apply_result_from_function<void(void*) noexcept, void*&>();
+ test_invalid_apply_result_from_function<void(void*) noexcept, void* const>();
+ test_invalid_apply_result_from_function<void(void*) noexcept, void* const&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, void*>();
+ test_invalid_apply_result<NoExceptCallable<bool>, void*&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, void* const>();
+ test_invalid_apply_result<NoExceptCallable<bool>, void* const&>();
+
+ // test plain aggregate
+ test_invalid_apply_result_from_function<void(), empty_aggregate>();
+ test_invalid_apply_result_from_function<void(), empty_aggregate&>();
+ test_invalid_apply_result_from_function<void(), const empty_aggregate>();
+ test_invalid_apply_result_from_function<void(), const empty_aggregate&>();
+ test_invalid_apply_result_from_function<void() noexcept, empty_aggregate>();
+ test_invalid_apply_result_from_function<void() noexcept, empty_aggregate&>();
+ test_invalid_apply_result_from_function<void() noexcept, const empty_aggregate>();
+ test_invalid_apply_result_from_function<void() noexcept, const empty_aggregate&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, empty_aggregate>();
+ test_invalid_apply_result<NoExceptCallable<bool>, empty_aggregate&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const empty_aggregate>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const empty_aggregate&>();
+
+ // test std::get-able class
+ test_invalid_apply_result_from_function<void(int), derived_from_tuple_int>();
+ test_invalid_apply_result_from_function<void(int), derived_from_tuple_int&>();
+ test_invalid_apply_result_from_function<void(int), const derived_from_tuple_int>();
+ test_invalid_apply_result_from_function<void(int), const derived_from_tuple_int&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, derived_from_tuple_int>();
+ test_invalid_apply_result_from_function<void(int) noexcept, derived_from_tuple_int&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const derived_from_tuple_int>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const derived_from_tuple_int&>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, derived_from_tuple_int>();
+ test_invalid_apply_result<NoExceptCallable<bool>, derived_from_tuple_int&>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const derived_from_tuple_int>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const derived_from_tuple_int&>();
+
+ // test built-in array
+ test_invalid_apply_result_from_function<void(int), int[1]>();
+ test_invalid_apply_result_from_function<void(int), int (&)[1]>();
+ test_invalid_apply_result_from_function<void(int), const int[1]>();
+ test_invalid_apply_result_from_function<void(int), const int (&)[1]>();
+ test_invalid_apply_result_from_function<void(int) noexcept, int[1]>();
+ test_invalid_apply_result_from_function<void(int) noexcept, int (&)[1]>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const int[1]>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const int (&)[1]>();
+
+ test_invalid_apply_result<NoExceptCallable<bool>, int[1]>();
+ test_invalid_apply_result<NoExceptCallable<bool>, int (&)[1]>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const int[1]>();
+ test_invalid_apply_result<NoExceptCallable<bool>, const int (&)[1]>();
+}
+
+void test_invalid_invocations() {
+ // test array
+ test_invalid_apply_result<void, std::array<int, 0>>();
+ test_invalid_apply_result<void*, std::array<int, 1>>();
+ test_invalid_apply_result<int, std::array<int, 2>>();
+ test_invalid_apply_result<int&, std::array<int, 3>>();
+ test_invalid_apply_result<int(int, int, int, int) const & noexcept, std::array<int, 4>>();
+
+ test_invalid_apply_result_from_function<void(int), std::array<int, 0>>();
+ test_invalid_apply_result_from_function<void(int), std::array<int, 0>&>();
+ test_invalid_apply_result_from_function<void(int), const std::array<int, 0>>();
+ test_invalid_apply_result_from_function<void(int), const std::array<int, 0>&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, std::array<int, 0>>();
+ test_invalid_apply_result_from_function<void(int) noexcept, std::array<int, 0>&>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const std::array<int, 0>>();
+ test_invalid_apply_result_from_function<void(int) noexcept, const std::array<int, 0>&>();
+ test_invalid_apply_result_from_function<void(int, long), std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int, long), std::array<int, 1>&>();
+ test_invalid_apply_result_from_function<void(int, long), const std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int, long), const std::array<int, 1>&>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, std::array<int, 1>&>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, const std::array<int, 1>>();
+ test_invalid_apply_result_from_function<void(int, long) noexcept, const std::array<int, 1>&>();
+
+ // test complex
+ test_invalid_apply_result<void, std::complex<float>>();
+ test_invalid_apply_result<void*, std::complex<float>>();
+ test_invalid_apply_result<int, std::complex<float>>();
+ test_invalid_apply_result<int&, std::complex<float>>();
+ test_invalid_apply_result<void(float, float) const & noexcept, std::complex<float>>();
+
+ test_invalid_apply_result<void, std::complex<double>>();
+ test_invalid_apply_result<void*, std::complex<double>>();
+ test_invalid_apply_result<int, std::complex<double>>();
+ test_invalid_apply_result<int&, std::complex<double>>();
+ test_invalid_apply_result<void(double, double) const & noexcept, std::complex<double>>();
+
+ test_invalid_apply_result<void, std::complex<long double>>();
+ test_invalid_apply_result<void*, std::complex<long double>>();
+ test_invalid_apply_result<int, std::complex<long double>>();
+ test_invalid_apply_result<int&, std::complex<long double>>();
+ test_invalid_apply_result<void(long double, long double) const & noexcept, std::complex<long double>>();
+
+ test_invalid_apply_result_from_function<void(float), std::complex<float>>();
+ test_invalid_apply_result_from_function<void(float), std::complex<float>&>();
+ test_invalid_apply_result_from_function<void(float), const std::complex<float>>();
+ test_invalid_apply_result_from_function<void(float), const std::complex<float>&>();
+ test_invalid_apply_result_from_function<void(float) noexcept, std::complex<float>>();
+ test_invalid_apply_result_from_function<void(float) noexcept, std::complex<float>&>();
+ test_invalid_apply_result_from_function<void(float) noexcept, const std::complex<float>>();
+ test_invalid_apply_result_from_function<void(float) noexcept, const std::complex<float>&>();
+
+ test_invalid_apply_result_from_function<void(double), std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double), std::complex<double>&>();
+ test_invalid_apply_result_from_function<void(double), const std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double), const std::complex<double>&>();
+ test_invalid_apply_result_from_function<void(double) noexcept, std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double) noexcept, std::complex<double>&>();
+ test_invalid_apply_result_from_function<void(double) noexcept, const std::complex<double>>();
+ test_invalid_apply_result_from_function<void(double) noexcept, const std::complex<double>&>();
+
+ test_invalid_apply_result_from_function<void(long double), std::complex<long double>>();
+ test_invalid_apply_result_from_function<void(long double), std::complex<long double>&>();
+ test_invalid_apply_result_from_function<void(long double), const std::complex<long double>>();
+ test_invalid_apply_result_from_function<void(long double), const std::complex<long double>&>();
+ test_invalid_apply_result_from_function<void(long double) noexcept, std::complex<long double>>();
+ test_invalid_apply_result_from_function<void(long double) noexcept, std::complex<long double>&>();
+ test_invalid_apply_result_from_function<void(long double) noexcept, const std::complex<long double>>();
+ test_invalid_apply_result_from_function<void(long double) noexcept, const std::complex<long double>&>();
+
+ // test subrange
+ using copyable_subrange = std::ranges::subrange<int*>;
+
+ test_invalid_apply_result<void, copyable_subrange>();
+ test_invalid_apply_result<void*, copyable_subrange>();
+ test_invalid_apply_result<int, copyable_subrange>();
+ test_invalid_apply_result<int&, copyable_subrange>();
+
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t), copyable_subrange>();
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t), copyable_subrange&>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t), const copyable_subrange>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t), const copyable_subrange&>();
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t) noexcept, copyable_subrange>();
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t) noexcept, copyable_subrange&>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t) noexcept, const copyable_subrange>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t) noexcept, const copyable_subrange&>();
+
+ using move_only_counted_iter = std::counted_iterator<cpp20_input_iterator<int*>>;
+ using move_only_subrange = std::ranges::subrange<move_only_counted_iter, std::default_sentinel_t>;
+
+ test_invalid_apply_result<void, move_only_subrange>();
+ test_invalid_apply_result<void*, move_only_subrange>();
+ test_invalid_apply_result<int, move_only_subrange>();
+ test_invalid_apply_result<int&, move_only_subrange>();
+
+ test_invalid_apply_result_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ move_only_subrange&>();
+ test_invalid_apply_result_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ const move_only_subrange>();
+ test_invalid_apply_result_from_function<void(move_only_counted_iter&, std::default_sentinel_t),
+ const move_only_subrange&>();
+ test_invalid_apply_result_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ move_only_subrange&>();
+ test_invalid_apply_result_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ const move_only_subrange>();
+ test_invalid_apply_result_from_function<void(move_only_counted_iter&, std::default_sentinel_t) noexcept,
+ const move_only_subrange&>();
+
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t), move_only_subrange>();
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t), move_only_subrange&>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t), const move_only_subrange>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t), const move_only_subrange&>();
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t) noexcept, move_only_subrange>();
+ test_invalid_apply_result_from_function<void(std::default_sentinel_t) noexcept, move_only_subrange&>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t) noexcept, const move_only_subrange>();
+ test_invalid_apply_result_from_function<int(std::default_sentinel_t) noexcept, const move_only_subrange&>();
+
+ // test tuple
+ test_invalid_apply_result<void, std::tuple<>>();
+ test_invalid_apply_result<void*, std::tuple<>>();
+ test_invalid_apply_result<int, std::tuple<int>>();
+ test_invalid_apply_result<int&, std::tuple<int>>();
+ test_invalid_apply_result<int() const&, std::tuple<>>();
+ test_invalid_apply_result<int() const & noexcept, std::tuple<>>();
+
+ test_invalid_apply_result_from_function<int(), std::tuple<int>>();
+ test_invalid_apply_result_from_function<int(), std::tuple<int>&>();
+ test_invalid_apply_result_from_function<int(), const std::tuple<int>>();
+ test_invalid_apply_result_from_function<int(), const std::tuple<int>&>();
+ test_invalid_apply_result_from_function<int() noexcept, std::tuple<int>>();
+ test_invalid_apply_result_from_function<int() noexcept, std::tuple<int>&>();
+ test_invalid_apply_result_from_function<int() noexcept, const std::tuple<int>>();
+ test_invalid_apply_result_from_function<int() noexcept, const std::tuple<int>&>();
+
+ // test pair
+ test_invalid_apply_result<void, std::pair<int, long>>();
+ test_invalid_apply_result<void*, std::pair<int, long>>();
+ test_invalid_apply_result<int, std::pair<int, long>>();
+ test_invalid_apply_result<int&, std::pair<int, long>>();
+
+ test_invalid_apply_result<int(int, long) const&, std::pair<int, long>>();
+ test_invalid_apply_result<int(int, long) const & noexcept, std::pair<int, long>>();
+
+ test_invalid_apply_result_from_function<int(), std::pair<int, long>>();
+ test_invalid_apply_result_from_function<void(int, long, long long), std::pair<int, long>&>();
+ test_invalid_apply_result_from_function<int&(int), const std::pair<int, long>>();
+ test_invalid_apply_result_from_function<long&(int&, long&), const std::pair<int, long>&>();
+ test_invalid_apply_result_from_function<int() noexcept, std::pair<int, long>>();
+ test_invalid_apply_result_from_function<void(int, long, long long) noexcept, std::pair<int, long>&>();
+ test_invalid_apply_result_from_function<int&(int) noexcept, const std::pair<int, long>>();
+ test_invalid_apply_result_from_function<long&(int&, long&) noexcept, const std::pair<int, long>&>();
+}
>From a700737384e80debf94f113862e40ddbdda8f223 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Tue, 5 Aug 2025 19:23:39 +0800
Subject: [PATCH 2/2] Address review comments (except for tests)
---
libcxx/docs/ReleaseNotes/22.rst | 2 --
libcxx/include/{__type_traits => __tuple}/is_applicable.h | 0
libcxx/include/module.modulemap.in | 8 ++++----
libcxx/include/type_traits | 2 +-
4 files changed, 5 insertions(+), 7 deletions(-)
rename libcxx/include/{__type_traits => __tuple}/is_applicable.h (100%)
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 05c375359a688..15bf46d44b07f 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -38,8 +38,6 @@ What's New in Libc++ 22.0.0?
Implemented Papers
------------------
-- P1317R2: Remove return type deduction in ``std::apply`` (`Github <https://github.com/llvm/llvm-project/issues/148183>`__)
- (Only components in ``<type_traits>`` are implemented.)
- P2321R2: ``zip`` (`Github <https://github.com/llvm/llvm-project/issues/105169>`__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release)
Improvements and New Features
diff --git a/libcxx/include/__type_traits/is_applicable.h b/libcxx/include/__tuple/is_applicable.h
similarity index 100%
rename from libcxx/include/__type_traits/is_applicable.h
rename to libcxx/include/__tuple/is_applicable.h
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 6766960144a83..4ffbb35c8ede4 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -112,10 +112,6 @@ module std_core [system] {
header "__type_traits/is_always_bitcastable.h"
export std_core.type_traits.integral_constant
}
- module is_applicable {
- header "__type_traits/is_applicable.h"
- export std_core.type_traits.integral_constant
- }
module is_arithmetic {
header "__type_traits/is_arithmetic.h"
export std_core.type_traits.integral_constant
@@ -2115,6 +2111,10 @@ module std [system] {
module tuple {
module find_index { header "__tuple/find_index.h" }
module ignore { header "__tuple/ignore.h" }
+ module is_applicable {
+ header "__tuple/is_applicable.h"
+ export std_core.type_traits.integral_constant
+ }
module make_tuple_types { header "__tuple/make_tuple_types.h" }
module sfinae_helpers { header "__tuple/sfinae_helpers.h" }
module tuple_element { header "__tuple/tuple_element.h" }
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index f8c3f744e07f4..9484be752af69 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -572,7 +572,7 @@ namespace std
# endif
# if _LIBCPP_STD_VER >= 26
-# include <__type_traits/is_applicable.h>
+# include <__tuple/is_applicable.h>
# endif
# include <version>
More information about the libcxx-commits
mailing list