1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
13 // is_nothrow_invocable
15 #include <type_traits>
19 #include "test_macros.h"
24 Implicit(int) noexcept
{}
27 struct ThrowsImplicit
{
28 ThrowsImplicit(int) {}
32 explicit Explicit(int) noexcept
{}
35 template <bool IsNoexcept
, class Ret
, class... Args
>
37 Ret
operator()(Args
&&...) const noexcept(IsNoexcept
);
41 template <class... Args
>
42 void operator()(Args
&&...) const noexcept
{}
45 template <class Fn
, class... Args
>
46 constexpr bool throws_invocable() {
47 return std::is_invocable
<Fn
, Args
...>::value
&&
48 !std::is_nothrow_invocable
<Fn
, Args
...>::value
;
51 template <class Ret
, class Fn
, class... Args
>
52 constexpr bool throws_invocable_r() {
53 return std::is_invocable_r
<Ret
, Fn
, Args
...>::value
&&
54 !std::is_nothrow_invocable_r
<Ret
, Fn
, Args
...>::value
;
57 void test_noexcept_function_pointers() {
59 void foo() noexcept
{}
60 static void bar() noexcept
{}
62 // Check that PMF's and function pointers actually work and that
63 // is_nothrow_invocable returns true for noexcept PMF's and function
65 static_assert(std::is_nothrow_invocable
<decltype(&Dummy::foo
), Dummy
&>::value
, "");
66 static_assert(std::is_nothrow_invocable
<decltype(&Dummy::bar
)>::value
, "");
69 int main(int, char**) {
70 using AbominableFunc
= void(...) const noexcept
;
71 // Non-callable things
73 static_assert(!std::is_nothrow_invocable
<void>::value
, "");
74 static_assert(!std::is_nothrow_invocable
<const void>::value
, "");
75 static_assert(!std::is_nothrow_invocable
<volatile void>::value
, "");
76 static_assert(!std::is_nothrow_invocable
<const volatile void>::value
, "");
77 static_assert(!std::is_nothrow_invocable
<std::nullptr_t
>::value
, "");
78 static_assert(!std::is_nothrow_invocable
<int>::value
, "");
79 static_assert(!std::is_nothrow_invocable
<double>::value
, "");
81 static_assert(!std::is_nothrow_invocable
<int[]>::value
, "");
82 static_assert(!std::is_nothrow_invocable
<int[3]>::value
, "");
84 static_assert(!std::is_nothrow_invocable
<int*>::value
, "");
85 static_assert(!std::is_nothrow_invocable
<const int*>::value
, "");
86 static_assert(!std::is_nothrow_invocable
<int const*>::value
, "");
88 static_assert(!std::is_nothrow_invocable
<int&>::value
, "");
89 static_assert(!std::is_nothrow_invocable
<const int&>::value
, "");
90 static_assert(!std::is_nothrow_invocable
<int&&>::value
, "");
92 static_assert(!std::is_nothrow_invocable
<int, std::vector
<int> >::value
,
94 static_assert(!std::is_nothrow_invocable
<int, std::vector
<int*> >::value
,
96 static_assert(!std::is_nothrow_invocable
<int, std::vector
<int**> >::value
,
99 static_assert(!std::is_nothrow_invocable
<AbominableFunc
>::value
, "");
102 static_assert(!std::is_nothrow_invocable
<int, int>::value
, "");
103 static_assert(!std::is_nothrow_invocable
<int, double, float>::value
, "");
104 static_assert(!std::is_nothrow_invocable
<int, char, float, double>::value
,
106 static_assert(!std::is_nothrow_invocable
<Sink
, AbominableFunc
>::value
, "");
107 static_assert(!std::is_nothrow_invocable
<Sink
, void>::value
, "");
108 static_assert(!std::is_nothrow_invocable
<Sink
, const volatile void>::value
,
111 static_assert(!std::is_nothrow_invocable_r
<int, void>::value
, "");
112 static_assert(!std::is_nothrow_invocable_r
<int, const void>::value
, "");
113 static_assert(!std::is_nothrow_invocable_r
<int, volatile void>::value
, "");
114 static_assert(!std::is_nothrow_invocable_r
<int, const volatile void>::value
,
116 static_assert(!std::is_nothrow_invocable_r
<int, std::nullptr_t
>::value
, "");
117 static_assert(!std::is_nothrow_invocable_r
<int, int>::value
, "");
118 static_assert(!std::is_nothrow_invocable_r
<int, double>::value
, "");
120 static_assert(!std::is_nothrow_invocable_r
<int, int[]>::value
, "");
121 static_assert(!std::is_nothrow_invocable_r
<int, int[3]>::value
, "");
123 static_assert(!std::is_nothrow_invocable_r
<int, int*>::value
, "");
124 static_assert(!std::is_nothrow_invocable_r
<int, const int*>::value
, "");
125 static_assert(!std::is_nothrow_invocable_r
<int, int const*>::value
, "");
127 static_assert(!std::is_nothrow_invocable_r
<int, int&>::value
, "");
128 static_assert(!std::is_nothrow_invocable_r
<int, const int&>::value
, "");
129 static_assert(!std::is_nothrow_invocable_r
<int, int&&>::value
, "");
131 static_assert(!std::is_nothrow_invocable_r
<int, std::vector
<int> >::value
,
133 static_assert(!std::is_nothrow_invocable_r
<int, std::vector
<int*> >::value
,
135 static_assert(!std::is_nothrow_invocable_r
<int, std::vector
<int**> >::value
,
137 static_assert(!std::is_nothrow_invocable_r
<void, AbominableFunc
>::value
,
141 static_assert(!std::is_nothrow_invocable_r
<int, int, int>::value
, "");
142 static_assert(!std::is_nothrow_invocable_r
<int, int, double, float>::value
,
145 !std::is_nothrow_invocable_r
<int, int, char, float, double>::value
, "");
147 !std::is_nothrow_invocable_r
<void, Sink
, AbominableFunc
>::value
, "");
148 static_assert(!std::is_nothrow_invocable_r
<void, Sink
, void>::value
, "");
150 !std::is_nothrow_invocable_r
<void, Sink
, const volatile void>::value
,
155 // Check that the conversion to the return type is properly checked
156 using Fn
= CallObject
<true, int>;
157 static_assert(std::is_nothrow_invocable_r
<Implicit
, Fn
>::value
, "");
158 static_assert(std::is_nothrow_invocable_r
<double, Fn
>::value
, "");
159 static_assert(std::is_nothrow_invocable_r
<const volatile void, Fn
>::value
,
161 static_assert(throws_invocable_r
<ThrowsImplicit
, Fn
>(), "");
162 static_assert(!std::is_nothrow_invocable
<Fn(), Explicit
>(), "");
165 // Check that the conversion to the parameters is properly checked
166 using Fn
= CallObject
<true, void, const Implicit
&, const ThrowsImplicit
&>;
168 std::is_nothrow_invocable
<Fn
, Implicit
&, ThrowsImplicit
&>::value
, "");
169 static_assert(std::is_nothrow_invocable
<Fn
, int, ThrowsImplicit
&>::value
,
171 static_assert(throws_invocable
<Fn
, int, int>(), "");
172 static_assert(!std::is_nothrow_invocable
<Fn
>::value
, "");
175 // Check that the noexcept-ness of function objects is checked.
176 using Fn
= CallObject
<true, void>;
177 using Fn2
= CallObject
<false, void>;
178 static_assert(std::is_nothrow_invocable
<Fn
>::value
, "");
179 static_assert(throws_invocable
<Fn2
>(), "");
182 // Check that PMD derefs are noexcept
183 using Fn
= int(Tag::*);
184 static_assert(std::is_nothrow_invocable
<Fn
, Tag
&>::value
, "");
185 static_assert(std::is_nothrow_invocable_r
<Implicit
, Fn
, Tag
&>::value
, "");
186 static_assert(throws_invocable_r
<ThrowsImplicit
, Fn
, Tag
&>(), "");
189 // Check that it's fine if the result type is non-moveable.
191 CantMove() = default;
192 CantMove(CantMove
&&) = delete;
195 static_assert(!std::is_move_constructible_v
<CantMove
>);
196 static_assert(!std::is_copy_constructible_v
<CantMove
>);
198 using Fn
= CantMove() noexcept
;
200 static_assert(std::is_nothrow_invocable_r
<CantMove
, Fn
>::value
);
201 static_assert(!std::is_nothrow_invocable_r
<CantMove
, Fn
, int>::value
);
203 static_assert(std::is_nothrow_invocable_r_v
<CantMove
, Fn
>);
204 static_assert(!std::is_nothrow_invocable_r_v
<CantMove
, Fn
, int>);
207 // Check for is_nothrow_invocable_v
208 using Fn
= CallObject
<true, int>;
209 static_assert(std::is_nothrow_invocable_v
<Fn
>, "");
210 static_assert(!std::is_nothrow_invocable_v
<Fn
, int>, "");
213 // Check for is_nothrow_invocable_r_v
214 using Fn
= CallObject
<true, int>;
215 static_assert(std::is_nothrow_invocable_r_v
<void, Fn
>, "");
216 static_assert(!std::is_nothrow_invocable_r_v
<int, Fn
, int>, "");
218 test_noexcept_function_pointers();