1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 // UNSUPPORTED: c++03, c++11, c++14
10
11 // is_invocable_r
12
13 #include <type_traits>
14
15 // Non-invocable types
16
17 static_assert(!std::is_invocable_r<void, void>::value);
18 static_assert(!std::is_invocable_r<void, int>::value);
19 static_assert(!std::is_invocable_r<void, int*>::value);
20 static_assert(!std::is_invocable_r<void, int&>::value);
21 static_assert(!std::is_invocable_r<void, int&&>::value);
22
23 // Result type matches
24
25 template <typename T>
26 T Return();
27
28 static_assert(std::is_invocable_r<int, decltype(Return<int>)>::value);
29 static_assert(std::is_invocable_r<char, decltype(Return<char>)>::value);
30 static_assert(std::is_invocable_r<int*, decltype(Return<int*>)>::value);
31 static_assert(std::is_invocable_r<int&, decltype(Return<int&>)>::value);
32 static_assert(std::is_invocable_r<int&&, decltype(Return<int&&>)>::value);
33
34 // void result type
35
36 // Any actual return type should be useable with a result type of void.
37 static_assert(std::is_invocable_r<void, decltype(Return<void>)>::value);
38 static_assert(std::is_invocable_r<void, decltype(Return<int>)>::value);
39 static_assert(std::is_invocable_r<void, decltype(Return<int*>)>::value);
40 static_assert(std::is_invocable_r<void, decltype(Return<int&>)>::value);
41 static_assert(std::is_invocable_r<void, decltype(Return<int&&>)>::value);
42
43 // const- and volatile-qualified void should work too.
44 static_assert(std::is_invocable_r<const void, decltype(Return<void>)>::value);
45 static_assert(std::is_invocable_r<const void, decltype(Return<int>)>::value);
46 static_assert(std::is_invocable_r<volatile void, decltype(Return<void>)>::value);
47 static_assert(std::is_invocable_r<volatile void, decltype(Return<int>)>::value);
48 static_assert(std::is_invocable_r<const volatile void, decltype(Return<void>)>::value);
49 static_assert(std::is_invocable_r<const volatile void, decltype(Return<int>)>::value);
50
51 // Conversion of result type
52
53 // It should be possible to use a result type to which the actual return type
54 // can be converted.
55 static_assert(std::is_invocable_r<char, decltype(Return<int>)>::value);
56 static_assert(std::is_invocable_r<const int*, decltype(Return<int*>)>::value);
57 static_assert(std::is_invocable_r<void*, decltype(Return<int*>)>::value);
58 static_assert(std::is_invocable_r<const int&, decltype(Return<int>)>::value);
59 static_assert(std::is_invocable_r<const int&, decltype(Return<int&>)>::value);
60 static_assert(std::is_invocable_r<const int&, decltype(Return<int&&>)>::value);
61 static_assert(std::is_invocable_r<const char&, decltype(Return<int>)>::value);
62
63 // But not a result type where the conversion doesn't work.
64 static_assert(!std::is_invocable_r<int, decltype(Return<void>)>::value);
65 static_assert(!std::is_invocable_r<int, decltype(Return<int*>)>::value);
66
67 // Non-moveable result type
68
69 // Define a type that can't be move-constructed.
70 struct CantMove {
71 CantMove() = default;
72 CantMove(CantMove&&) = delete;
73 };
74
75 static_assert(!std::is_move_constructible_v<CantMove>);
76 static_assert(!std::is_copy_constructible_v<CantMove>);
77
78 // Define functions that return that type.
MakeCantMove()79 CantMove MakeCantMove() { return {}; }
MakeCantMoveWithArg(int)80 CantMove MakeCantMoveWithArg(int) { return {}; }
81
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();
85
86 // Therefore std::is_invocable_r should agree that they can be invoked to yield
87 // a CantMove.
88 static_assert(std::is_invocable_r<CantMove, decltype(MakeCantMove)>::value);
89 static_assert(std::is_invocable_r<CantMove, decltype(MakeCantMoveWithArg), int>::value);
90
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<int, decltype(MakeCantMove)>::value);
94
95 // And the argument types should still be important.
96 static_assert(!std::is_invocable_r<CantMove, decltype(MakeCantMove), int>::value);
97 static_assert(!std::is_invocable_r<CantMove, decltype(MakeCantMoveWithArg)>::value);
98
99 // is_invocable_r
100
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);
104