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 #include <type_traits>
15 // Non-invocable types
17 static_assert(!std::is_invocable_r_v
<void, void>);
18 static_assert(!std::is_invocable_r_v
<void, int>);
19 static_assert(!std::is_invocable_r_v
<void, int*>);
20 static_assert(!std::is_invocable_r_v
<void, int&>);
21 static_assert(!std::is_invocable_r_v
<void, int&&>);
23 // Result type matches
28 static_assert(std::is_invocable_r_v
<int, decltype(Return
<int>)>);
29 static_assert(std::is_invocable_r_v
<char, decltype(Return
<char>)>);
30 static_assert(std::is_invocable_r_v
<int*, decltype(Return
<int*>)>);
31 static_assert(std::is_invocable_r_v
<int&, decltype(Return
<int&>)>);
32 static_assert(std::is_invocable_r_v
<int&&, decltype(Return
<int&&>)>);
36 // Any actual return type should be useable with a result type of void.
37 static_assert(std::is_invocable_r_v
<void, decltype(Return
<void>)>);
38 static_assert(std::is_invocable_r_v
<void, decltype(Return
<int>)>);
39 static_assert(std::is_invocable_r_v
<void, decltype(Return
<int*>)>);
40 static_assert(std::is_invocable_r_v
<void, decltype(Return
<int&>)>);
41 static_assert(std::is_invocable_r_v
<void, decltype(Return
<int&&>)>);
43 // const- and volatile-qualified void should work too.
44 static_assert(std::is_invocable_r_v
<const void, decltype(Return
<void>)>);
45 static_assert(std::is_invocable_r_v
<const void, decltype(Return
<int>)>);
46 static_assert(std::is_invocable_r_v
<volatile void, decltype(Return
<void>)>);
47 static_assert(std::is_invocable_r_v
<volatile void, decltype(Return
<int>)>);
48 static_assert(std::is_invocable_r_v
<const volatile void, decltype(Return
<void>)>);
49 static_assert(std::is_invocable_r_v
<const volatile void, decltype(Return
<int>)>);
51 // Conversion of result type
53 // It should be possible to use a result type to which the actual return type
55 static_assert(std::is_invocable_r_v
<char, decltype(Return
<int>)>);
56 static_assert(std::is_invocable_r_v
<const int*, decltype(Return
<int*>)>);
57 static_assert(std::is_invocable_r_v
<void*, decltype(Return
<int*>)>);
58 static_assert(std::is_invocable_r_v
<const int&, decltype(Return
<int>)>);
59 static_assert(std::is_invocable_r_v
<const int&, decltype(Return
<int&>)>);
60 static_assert(std::is_invocable_r_v
<const int&, decltype(Return
<int&&>)>);
61 static_assert(std::is_invocable_r_v
<const char&, decltype(Return
<int>)>);
63 // But not a result type where the conversion doesn't work.
64 static_assert(!std::is_invocable_r_v
<int, decltype(Return
<void>)>);
65 static_assert(!std::is_invocable_r_v
<int, decltype(Return
<int*>)>);
67 // Non-moveable result type
69 // Define a type that can't be move-constructed.
72 CantMove(CantMove
&&) = delete;
75 static_assert(!std::is_move_constructible_v
<CantMove
>);
76 static_assert(!std::is_copy_constructible_v
<CantMove
>);
78 // Define functions that return that type.
79 CantMove
MakeCantMove() { return {}; }
80 CantMove
MakeCantMoveWithArg(int) { return {}; }
82 // Assumption check: it should be possible to call one of those functions and
83 // use it to initialize a CantMove object.
84 CantMove cant_move
= MakeCantMove();
86 // Therefore std::is_invocable_r should agree that they can be invoked to yield
88 static_assert(std::is_invocable_r_v
<CantMove
, decltype(MakeCantMove
)>);
89 static_assert(std::is_invocable_r_v
<CantMove
, decltype(MakeCantMoveWithArg
), int>);
91 // Of course it still shouldn't be possible to call one of the functions and get
92 // back some other type.
93 static_assert(!std::is_invocable_r_v
<int, decltype(MakeCantMove
)>);
95 // And the argument types should still be important.
96 static_assert(!std::is_invocable_r_v
<CantMove
, decltype(MakeCantMove
), int>);
97 static_assert(!std::is_invocable_r_v
<CantMove
, decltype(MakeCantMoveWithArg
)>);
101 // The struct form should be available too, not just the _v variant.
102 static_assert(std::is_invocable_r
<int, decltype(Return
<int>)>::value
);
103 static_assert(!std::is_invocable_r
<int*, decltype(Return
<int>)>::value
);