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
17static_assert(!std::is_invocable_r_v<void, void>);
18static_assert(!std::is_invocable_r_v<void, int>);
19static_assert(!std::is_invocable_r_v<void, int*>);
20static_assert(!std::is_invocable_r_v<void, int&>);
21static_assert(!std::is_invocable_r_v<void, int&&>);
22
23// Result type matches
24
25template <typename T>
26T Return();
27
28static_assert(std::is_invocable_r_v<int, decltype(Return<int>)>);
29static_assert(std::is_invocable_r_v<char, decltype(Return<char>)>);
30static_assert(std::is_invocable_r_v<int*, decltype(Return<int*>)>);
31static_assert(std::is_invocable_r_v<int&, decltype(Return<int&>)>);
32static_assert(std::is_invocable_r_v<int&&, decltype(Return<int&&>)>);
33
34// void result type
35
36// Any actual return type should be useable with a result type of void.
37static_assert(std::is_invocable_r_v<void, decltype(Return<void>)>);
38static_assert(std::is_invocable_r_v<void, decltype(Return<int>)>);
39static_assert(std::is_invocable_r_v<void, decltype(Return<int*>)>);
40static_assert(std::is_invocable_r_v<void, decltype(Return<int&>)>);
41static_assert(std::is_invocable_r_v<void, decltype(Return<int&&>)>);
42
43// const- and volatile-qualified void should work too.
44static_assert(std::is_invocable_r_v<const void, decltype(Return<void>)>);
45static_assert(std::is_invocable_r_v<const void, decltype(Return<int>)>);
46static_assert(std::is_invocable_r_v<volatile void, decltype(Return<void>)>);
47static_assert(std::is_invocable_r_v<volatile void, decltype(Return<int>)>);
48static_assert(std::is_invocable_r_v<const volatile void, decltype(Return<void>)>);
49static_assert(std::is_invocable_r_v<const volatile void, decltype(Return<int>)>);
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.
55static_assert(std::is_invocable_r_v<char, decltype(Return<int>)>);
56static_assert(std::is_invocable_r_v<const int*, decltype(Return<int*>)>);
57static_assert(std::is_invocable_r_v<void*, decltype(Return<int*>)>);
58static_assert(std::is_invocable_r_v<const int&, decltype(Return<int>)>);
59static_assert(std::is_invocable_r_v<const int&, decltype(Return<int&>)>);
60static_assert(std::is_invocable_r_v<const int&, decltype(Return<int&&>)>);
61static_assert(std::is_invocable_r_v<const char&, decltype(Return<int>)>);
62
63// But not a result type where the conversion doesn't work.
64static_assert(!std::is_invocable_r_v<int, decltype(Return<void>)>);
65static_assert(!std::is_invocable_r_v<int, decltype(Return<int*>)>);
66
67// Non-moveable result type
68
69// Define a type that can't be move-constructed.
70struct CantMove {
71 CantMove() = default;
72 CantMove(CantMove&&) = delete;
73};
74
75static_assert(!std::is_move_constructible_v<CantMove>);
76static_assert(!std::is_copy_constructible_v<CantMove>);
77
78// Define functions that return that type.
79CantMove MakeCantMove() { return {}; }
80CantMove 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.
84CantMove cant_move = MakeCantMove();
85
86// Therefore std::is_invocable_r should agree that they can be invoked to yield
87// a CantMove.
88static_assert(std::is_invocable_r_v<CantMove, decltype(MakeCantMove)>);
89static_assert(std::is_invocable_r_v<CantMove, decltype(MakeCantMoveWithArg), int>);
90
91// Of course it still shouldn't be possible to call one of the functions and get
92// back some other type.
93static_assert(!std::is_invocable_r_v<int, decltype(MakeCantMove)>);
94
95// And the argument types should still be important.
96static_assert(!std::is_invocable_r_v<CantMove, decltype(MakeCantMove), int>);
97static_assert(!std::is_invocable_r_v<CantMove, decltype(MakeCantMoveWithArg)>);
98
99// is_invocable_r
100
101// The struct form should be available too, not just the _v variant.
102static_assert(std::is_invocable_r<int, decltype(Return<int>)>::value);
103static_assert(!std::is_invocable_r<int*, decltype(Return<int>)>::value);
104

source code of libcxx/test/std/utilities/meta/meta.rel/is_invocable_r_v.compile.pass.cpp