xref: /llvm-project/libcxx/test/std/utilities/meta/meta.rel/is_invocable_r.compile.pass.cpp (revision c3a24882903df5b25c011628162e82e47401f71f)
1*c3a24882SAaron Jacobs //===----------------------------------------------------------------------===//
2*c3a24882SAaron Jacobs //
3*c3a24882SAaron Jacobs // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c3a24882SAaron Jacobs // See https://llvm.org/LICENSE.txt for license information.
5*c3a24882SAaron Jacobs // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c3a24882SAaron Jacobs //
7*c3a24882SAaron Jacobs //===----------------------------------------------------------------------===//
8*c3a24882SAaron Jacobs 
9*c3a24882SAaron Jacobs // UNSUPPORTED: c++03, c++11, c++14
10*c3a24882SAaron Jacobs 
11*c3a24882SAaron Jacobs // is_invocable_r
12*c3a24882SAaron Jacobs 
13*c3a24882SAaron Jacobs #include <type_traits>
14*c3a24882SAaron Jacobs 
15*c3a24882SAaron Jacobs // Non-invocable types
16*c3a24882SAaron Jacobs 
17*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<void, void>::value);
18*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<void, int>::value);
19*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<void, int*>::value);
20*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<void, int&>::value);
21*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<void, int&&>::value);
22*c3a24882SAaron Jacobs 
23*c3a24882SAaron Jacobs // Result type matches
24*c3a24882SAaron Jacobs 
25*c3a24882SAaron Jacobs template <typename T>
26*c3a24882SAaron Jacobs T Return();
27*c3a24882SAaron Jacobs 
28*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<int, decltype(Return<int>)>::value);
29*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<char, decltype(Return<char>)>::value);
30*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<int*, decltype(Return<int*>)>::value);
31*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<int&, decltype(Return<int&>)>::value);
32*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<int&&, decltype(Return<int&&>)>::value);
33*c3a24882SAaron Jacobs 
34*c3a24882SAaron Jacobs // void result type
35*c3a24882SAaron Jacobs 
36*c3a24882SAaron Jacobs // Any actual return type should be useable with a result type of void.
37*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<void, decltype(Return<void>)>::value);
38*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<void, decltype(Return<int>)>::value);
39*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<void, decltype(Return<int*>)>::value);
40*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<void, decltype(Return<int&>)>::value);
41*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<void, decltype(Return<int&&>)>::value);
42*c3a24882SAaron Jacobs 
43*c3a24882SAaron Jacobs // const- and volatile-qualified void should work too.
44*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const void, decltype(Return<void>)>::value);
45*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const void, decltype(Return<int>)>::value);
46*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<volatile void, decltype(Return<void>)>::value);
47*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<volatile void, decltype(Return<int>)>::value);
48*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const volatile void, decltype(Return<void>)>::value);
49*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const volatile void, decltype(Return<int>)>::value);
50*c3a24882SAaron Jacobs 
51*c3a24882SAaron Jacobs // Conversion of result type
52*c3a24882SAaron Jacobs 
53*c3a24882SAaron Jacobs // It should be possible to use a result type to which the actual return type
54*c3a24882SAaron Jacobs // can be converted.
55*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<char, decltype(Return<int>)>::value);
56*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const int*, decltype(Return<int*>)>::value);
57*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<void*, decltype(Return<int*>)>::value);
58*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const int&, decltype(Return<int>)>::value);
59*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const int&, decltype(Return<int&>)>::value);
60*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const int&, decltype(Return<int&&>)>::value);
61*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<const char&, decltype(Return<int>)>::value);
62*c3a24882SAaron Jacobs 
63*c3a24882SAaron Jacobs // But not a result type where the conversion doesn't work.
64*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<int, decltype(Return<void>)>::value);
65*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<int, decltype(Return<int*>)>::value);
66*c3a24882SAaron Jacobs 
67*c3a24882SAaron Jacobs // Non-moveable result type
68*c3a24882SAaron Jacobs 
69*c3a24882SAaron Jacobs // Define a type that can't be move-constructed.
70*c3a24882SAaron Jacobs struct CantMove {
71*c3a24882SAaron Jacobs   CantMove() = default;
72*c3a24882SAaron Jacobs   CantMove(CantMove&&) = delete;
73*c3a24882SAaron Jacobs };
74*c3a24882SAaron Jacobs 
75*c3a24882SAaron Jacobs static_assert(!std::is_move_constructible_v<CantMove>);
76*c3a24882SAaron Jacobs static_assert(!std::is_copy_constructible_v<CantMove>);
77*c3a24882SAaron Jacobs 
78*c3a24882SAaron Jacobs // Define functions that return that type.
MakeCantMove()79*c3a24882SAaron Jacobs CantMove MakeCantMove() { return {}; }
MakeCantMoveWithArg(int)80*c3a24882SAaron Jacobs CantMove MakeCantMoveWithArg(int) { return {}; }
81*c3a24882SAaron Jacobs 
82*c3a24882SAaron Jacobs // Assumption check: it should be possible to call one of those functions and
83*c3a24882SAaron Jacobs // use it to initialize a CantMove object.
84*c3a24882SAaron Jacobs CantMove cant_move = MakeCantMove();
85*c3a24882SAaron Jacobs 
86*c3a24882SAaron Jacobs // Therefore std::is_invocable_r should agree that they can be invoked to yield
87*c3a24882SAaron Jacobs // a CantMove.
88*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<CantMove, decltype(MakeCantMove)>::value);
89*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<CantMove, decltype(MakeCantMoveWithArg), int>::value);
90*c3a24882SAaron Jacobs 
91*c3a24882SAaron Jacobs // Of course it still shouldn't be possible to call one of the functions and get
92*c3a24882SAaron Jacobs // back some other type.
93*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<int, decltype(MakeCantMove)>::value);
94*c3a24882SAaron Jacobs 
95*c3a24882SAaron Jacobs // And the argument types should still be important.
96*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<CantMove, decltype(MakeCantMove), int>::value);
97*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<CantMove, decltype(MakeCantMoveWithArg)>::value);
98*c3a24882SAaron Jacobs 
99*c3a24882SAaron Jacobs // is_invocable_r
100*c3a24882SAaron Jacobs 
101*c3a24882SAaron Jacobs // The struct form should be available too, not just the _v variant.
102*c3a24882SAaron Jacobs static_assert(std::is_invocable_r<int, decltype(Return<int>)>::value);
103*c3a24882SAaron Jacobs static_assert(!std::is_invocable_r<int*, decltype(Return<int>)>::value);
104