File: is_invocable_r.compile.pass.cpp

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (103 lines) | stat: -rw-r--r-- 4,525 bytes parent folder | download | duplicates (14)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// is_invocable_r

#include <type_traits>

// Non-invocable types

static_assert(!std::is_invocable_r<void, void>::value);
static_assert(!std::is_invocable_r<void, int>::value);
static_assert(!std::is_invocable_r<void, int*>::value);
static_assert(!std::is_invocable_r<void, int&>::value);
static_assert(!std::is_invocable_r<void, int&&>::value);

// Result type matches

template <typename T>
T Return();

static_assert(std::is_invocable_r<int, decltype(Return<int>)>::value);
static_assert(std::is_invocable_r<char, decltype(Return<char>)>::value);
static_assert(std::is_invocable_r<int*, decltype(Return<int*>)>::value);
static_assert(std::is_invocable_r<int&, decltype(Return<int&>)>::value);
static_assert(std::is_invocable_r<int&&, decltype(Return<int&&>)>::value);

// void result type

// Any actual return type should be useable with a result type of void.
static_assert(std::is_invocable_r<void, decltype(Return<void>)>::value);
static_assert(std::is_invocable_r<void, decltype(Return<int>)>::value);
static_assert(std::is_invocable_r<void, decltype(Return<int*>)>::value);
static_assert(std::is_invocable_r<void, decltype(Return<int&>)>::value);
static_assert(std::is_invocable_r<void, decltype(Return<int&&>)>::value);

// const- and volatile-qualified void should work too.
static_assert(std::is_invocable_r<const void, decltype(Return<void>)>::value);
static_assert(std::is_invocable_r<const void, decltype(Return<int>)>::value);
static_assert(std::is_invocable_r<volatile void, decltype(Return<void>)>::value);
static_assert(std::is_invocable_r<volatile void, decltype(Return<int>)>::value);
static_assert(std::is_invocable_r<const volatile void, decltype(Return<void>)>::value);
static_assert(std::is_invocable_r<const volatile void, decltype(Return<int>)>::value);

// Conversion of result type

// It should be possible to use a result type to which the actual return type
// can be converted.
static_assert(std::is_invocable_r<char, decltype(Return<int>)>::value);
static_assert(std::is_invocable_r<const int*, decltype(Return<int*>)>::value);
static_assert(std::is_invocable_r<void*, decltype(Return<int*>)>::value);
static_assert(std::is_invocable_r<const int&, decltype(Return<int>)>::value);
static_assert(std::is_invocable_r<const int&, decltype(Return<int&>)>::value);
static_assert(std::is_invocable_r<const int&, decltype(Return<int&&>)>::value);
static_assert(std::is_invocable_r<const char&, decltype(Return<int>)>::value);

// But not a result type where the conversion doesn't work.
static_assert(!std::is_invocable_r<int, decltype(Return<void>)>::value);
static_assert(!std::is_invocable_r<int, decltype(Return<int*>)>::value);

// Non-moveable result type

// Define a type that can't be move-constructed.
struct CantMove {
  CantMove() = default;
  CantMove(CantMove&&) = delete;
};

static_assert(!std::is_move_constructible_v<CantMove>);
static_assert(!std::is_copy_constructible_v<CantMove>);

// Define functions that return that type.
CantMove MakeCantMove() { return {}; }
CantMove MakeCantMoveWithArg(int) { return {}; }

// Assumption check: it should be possible to call one of those functions and
// use it to initialize a CantMove object.
CantMove cant_move = MakeCantMove();

// Therefore std::is_invocable_r should agree that they can be invoked to yield
// a CantMove.
static_assert(std::is_invocable_r<CantMove, decltype(MakeCantMove)>::value);
static_assert(std::is_invocable_r<CantMove, decltype(MakeCantMoveWithArg), int>::value);

// Of course it still shouldn't be possible to call one of the functions and get
// back some other type.
static_assert(!std::is_invocable_r<int, decltype(MakeCantMove)>::value);

// And the argument types should still be important.
static_assert(!std::is_invocable_r<CantMove, decltype(MakeCantMove), int>::value);
static_assert(!std::is_invocable_r<CantMove, decltype(MakeCantMoveWithArg)>::value);

// is_invocable_r

// The struct form should be available too, not just the _v variant.
static_assert(std::is_invocable_r<int, decltype(Return<int>)>::value);
static_assert(!std::is_invocable_r<int*, decltype(Return<int>)>::value);