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
16 #include <type_traits>
22 Implicit(int) noexcept
{}
25 struct ThrowsImplicit
{
26 ThrowsImplicit(int) {}
30 explicit Explicit(int) noexcept
{}
33 template <bool IsNoexcept
, class Ret
, class... Args
>
35 Ret
operator()(Args
&&...) const noexcept(IsNoexcept
);
39 template <class... Args
>
40 void operator()(Args
&&...) const noexcept
{}
43 template <class Fn
, class... Args
>
44 constexpr bool throws_invocable() {
45 return std::is_invocable
<Fn
, Args
...>::value
&&
46 !std::is_nothrow_invocable
<Fn
, Args
...>::value
;
49 template <class Ret
, class Fn
, class... Args
>
50 constexpr bool throws_invocable_r() {
51 return std::is_invocable_r
<Ret
, Fn
, Args
...>::value
&&
52 !std::is_nothrow_invocable_r
<Ret
, Fn
, Args
...>::value
;
55 void test_noexcept_function_pointers() {
57 void foo() noexcept
{}
58 static void bar() noexcept
{}
60 // Check that PMF's and function pointers actually work and that
61 // is_nothrow_invocable returns true for noexcept PMF's and function
63 static_assert(std::is_nothrow_invocable
<decltype(&Dummy::foo
), Dummy
&>::value
, "");
64 static_assert(std::is_nothrow_invocable
<decltype(&Dummy::bar
)>::value
, "");
67 int main(int, char**) {
68 using AbominableFunc
= void(...) const noexcept
;
69 // Non-callable things
71 static_assert(!std::is_nothrow_invocable
<void>::value
, "");
72 static_assert(!std::is_nothrow_invocable
<const void>::value
, "");
73 static_assert(!std::is_nothrow_invocable
<volatile void>::value
, "");
74 static_assert(!std::is_nothrow_invocable
<const volatile void>::value
, "");
75 static_assert(!std::is_nothrow_invocable
<std::nullptr_t
>::value
, "");
76 static_assert(!std::is_nothrow_invocable
<int>::value
, "");
77 static_assert(!std::is_nothrow_invocable
<double>::value
, "");
79 static_assert(!std::is_nothrow_invocable
<int[]>::value
, "");
80 static_assert(!std::is_nothrow_invocable
<int[3]>::value
, "");
82 static_assert(!std::is_nothrow_invocable
<int*>::value
, "");
83 static_assert(!std::is_nothrow_invocable
<const int*>::value
, "");
84 static_assert(!std::is_nothrow_invocable
<int const*>::value
, "");
86 static_assert(!std::is_nothrow_invocable
<int&>::value
, "");
87 static_assert(!std::is_nothrow_invocable
<const int&>::value
, "");
88 static_assert(!std::is_nothrow_invocable
<int&&>::value
, "");
90 static_assert(!std::is_nothrow_invocable
<int, std::vector
<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
,
97 static_assert(!std::is_nothrow_invocable
<AbominableFunc
>::value
, "");
100 static_assert(!std::is_nothrow_invocable
<int, int>::value
, "");
101 static_assert(!std::is_nothrow_invocable
<int, double, float>::value
, "");
102 static_assert(!std::is_nothrow_invocable
<int, char, float, double>::value
,
104 static_assert(!std::is_nothrow_invocable
<Sink
, AbominableFunc
>::value
, "");
105 static_assert(!std::is_nothrow_invocable
<Sink
, void>::value
, "");
106 static_assert(!std::is_nothrow_invocable
<Sink
, const volatile void>::value
,
109 static_assert(!std::is_nothrow_invocable_r
<int, void>::value
, "");
110 static_assert(!std::is_nothrow_invocable_r
<int, const void>::value
, "");
111 static_assert(!std::is_nothrow_invocable_r
<int, volatile void>::value
, "");
112 static_assert(!std::is_nothrow_invocable_r
<int, const volatile void>::value
,
114 static_assert(!std::is_nothrow_invocable_r
<int, std::nullptr_t
>::value
, "");
115 static_assert(!std::is_nothrow_invocable_r
<int, int>::value
, "");
116 static_assert(!std::is_nothrow_invocable_r
<int, double>::value
, "");
118 static_assert(!std::is_nothrow_invocable_r
<int, int[]>::value
, "");
119 static_assert(!std::is_nothrow_invocable_r
<int, int[3]>::value
, "");
121 static_assert(!std::is_nothrow_invocable_r
<int, int*>::value
, "");
122 static_assert(!std::is_nothrow_invocable_r
<int, const int*>::value
, "");
123 static_assert(!std::is_nothrow_invocable_r
<int, int const*>::value
, "");
125 static_assert(!std::is_nothrow_invocable_r
<int, int&>::value
, "");
126 static_assert(!std::is_nothrow_invocable_r
<int, const int&>::value
, "");
127 static_assert(!std::is_nothrow_invocable_r
<int, int&&>::value
, "");
129 static_assert(!std::is_nothrow_invocable_r
<int, std::vector
<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
<void, AbominableFunc
>::value
,
139 static_assert(!std::is_nothrow_invocable_r
<int, int, int>::value
, "");
140 static_assert(!std::is_nothrow_invocable_r
<int, int, double, float>::value
,
143 !std::is_nothrow_invocable_r
<int, int, char, float, double>::value
, "");
145 !std::is_nothrow_invocable_r
<void, Sink
, AbominableFunc
>::value
, "");
146 static_assert(!std::is_nothrow_invocable_r
<void, Sink
, void>::value
, "");
148 !std::is_nothrow_invocable_r
<void, Sink
, const volatile void>::value
,
153 // Check that the conversion to the return type is properly checked
154 using Fn
= CallObject
<true, int>;
155 static_assert(std::is_nothrow_invocable_r
<Implicit
, Fn
>::value
, "");
156 static_assert(std::is_nothrow_invocable_r
<double, Fn
>::value
, "");
157 static_assert(std::is_nothrow_invocable_r
<const volatile void, Fn
>::value
,
159 static_assert(throws_invocable_r
<ThrowsImplicit
, Fn
>(), "");
160 static_assert(!std::is_nothrow_invocable
<Fn(), Explicit
>(), "");
163 // Check that the conversion to the parameters is properly checked
164 using Fn
= CallObject
<true, void, const Implicit
&, const ThrowsImplicit
&>;
166 std::is_nothrow_invocable
<Fn
, Implicit
&, ThrowsImplicit
&>::value
, "");
167 static_assert(std::is_nothrow_invocable
<Fn
, int, ThrowsImplicit
&>::value
,
169 static_assert(throws_invocable
<Fn
, int, int>(), "");
170 static_assert(!std::is_nothrow_invocable
<Fn
>::value
, "");
173 // Check that the noexcept-ness of function objects is checked.
174 using Fn
= CallObject
<true, void>;
175 using Fn2
= CallObject
<false, void>;
176 static_assert(std::is_nothrow_invocable
<Fn
>::value
, "");
177 static_assert(throws_invocable
<Fn2
>(), "");
180 // Check that PMD derefs are noexcept
181 using Fn
= int(Tag::*);
182 static_assert(std::is_nothrow_invocable
<Fn
, Tag
&>::value
, "");
183 static_assert(std::is_nothrow_invocable_r
<Implicit
, Fn
, Tag
&>::value
, "");
184 static_assert(throws_invocable_r
<ThrowsImplicit
, Fn
, Tag
&>(), "");
187 // Check that it's fine if the result type is non-moveable.
189 CantMove() = default;
190 CantMove(CantMove
&&) = delete;
193 static_assert(!std::is_move_constructible_v
<CantMove
>);
194 static_assert(!std::is_copy_constructible_v
<CantMove
>);
196 using Fn
= CantMove() noexcept
;
198 static_assert(std::is_nothrow_invocable_r
<CantMove
, Fn
>::value
);
199 static_assert(!std::is_nothrow_invocable_r
<CantMove
, Fn
, int>::value
);
201 static_assert(std::is_nothrow_invocable_r_v
<CantMove
, Fn
>);
202 static_assert(!std::is_nothrow_invocable_r_v
<CantMove
, Fn
, int>);
205 // Check for is_nothrow_invocable_v
206 using Fn
= CallObject
<true, int>;
207 static_assert(std::is_nothrow_invocable_v
<Fn
>, "");
208 static_assert(!std::is_nothrow_invocable_v
<Fn
, int>, "");
211 // Check for is_nothrow_invocable_r_v
212 using Fn
= CallObject
<true, int>;
213 static_assert(std::is_nothrow_invocable_r_v
<void, Fn
>, "");
214 static_assert(!std::is_nothrow_invocable_r_v
<int, Fn
, int>, "");
216 test_noexcept_function_pointers();