Skip to content

Commit 35078f3

Browse files
Constexprize bind_front and bind_back tests (#3117)
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
1 parent 6794a6a commit 35078f3

File tree

2 files changed

+78
-65
lines changed

2 files changed

+78
-65
lines changed

tests/std/tests/P0356R5_bind_front/test.cpp

+47-38
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ constexpr int f3(int x, int y, int z) {
3030
struct Cat {
3131
string name;
3232

33-
string noise(const string& s) const {
33+
constexpr string noise(const string& s) const {
3434
return name + " says " + s;
3535
}
3636
};
@@ -53,6 +53,26 @@ struct DetectQualifiers {
5353
}
5454
};
5555

56+
_CONSTEXPR23 void test_movable_only_types() {
57+
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
58+
if (up1 && up2) {
59+
return make_unique<int>(*up1 + *up2);
60+
} else if (up1) {
61+
return make_unique<int>(*up1 * -1);
62+
} else if (up2) {
63+
return make_unique<int>(*up2 * -10);
64+
} else {
65+
return make_unique<int>(-9000);
66+
}
67+
};
68+
auto bound6 = bind_front(move(unique_lambda), make_unique<int>(34));
69+
assert(*unique_lambda(make_unique<int>(56)) == -560);
70+
assert(*move(bound6)() == 1234);
71+
auto bound7 = move(bound6);
72+
assert(*move(bound6)() == -9000);
73+
assert(*move(bound7)() == 1234);
74+
}
75+
5676
constexpr bool test_constexpr() {
5777
// Test varying numbers of arguments.
5878
assert(bind_front(f0)() == 1729);
@@ -92,13 +112,39 @@ constexpr bool test_constexpr() {
92112
bound1(4);
93113
assert(value == 234);
94114

115+
// Test PMFs.
116+
Cat cat{"Peppermint"};
117+
auto bound2 = bind_front(&Cat::noise, cat); // stores a copy
118+
assert(bound2("meow") == "Peppermint says meow");
119+
cat.name = "Fluffy";
120+
assert(cat.noise("hiss") == "Fluffy says hiss");
121+
assert(bound2("purr") == "Peppermint says purr");
122+
123+
auto bound3 = bind_front(&Cat::noise, &cat); // stores a pointer
124+
assert(bound3("MEOW") == "Fluffy says MEOW");
125+
cat.name = "Peppermint";
126+
assert(bound3("PURR") == "Peppermint says PURR");
127+
128+
auto bound4 = bind_front(&Cat::noise, ref(cat)); // stores a reference_wrapper
129+
assert(bound4("Why do you keep renaming me?") == "Peppermint says Why do you keep renaming me?");
130+
cat.name = "Cat";
131+
assert(bound4("You can't rename me anymore, Human") == "Cat says You can't rename me anymore, Human");
132+
95133
// Test "perfect forwarding call wrapper" behavior.
96134
auto bound5 = bind_front(DetectQualifiers{});
97135
assert(bound5() == "modifiable lvalue");
98136
assert(as_const(bound5)() == "const lvalue");
99137
assert(move(bound5)() == "modifiable rvalue");
100138
assert(move(as_const(bound5))() == "const rvalue");
101139

140+
#if _HAS_CXX23
141+
test_movable_only_types();
142+
#else // _HAS_CXX23
143+
if (!is_constant_evaluated()) {
144+
test_movable_only_types();
145+
}
146+
#endif // _HAS_CXX23
147+
102148
// Test decay when binding.
103149
const int arr[] = {11, 22, 33};
104150
const int three = 3;
@@ -128,43 +174,6 @@ int main() {
128174
assert(test_constexpr());
129175
static_assert(test_constexpr());
130176

131-
// Test PMFs.
132-
Cat cat{"Peppermint"};
133-
auto bound2 = bind_front(&Cat::noise, cat); // stores a copy
134-
assert(bound2("meow") == "Peppermint says meow");
135-
cat.name = "Fluffy";
136-
assert(cat.noise("hiss") == "Fluffy says hiss");
137-
assert(bound2("purr") == "Peppermint says purr");
138-
139-
auto bound3 = bind_front(&Cat::noise, &cat); // stores a pointer
140-
assert(bound3("MEOW") == "Fluffy says MEOW");
141-
cat.name = "Peppermint";
142-
assert(bound3("PURR") == "Peppermint says PURR");
143-
144-
auto bound4 = bind_front(&Cat::noise, ref(cat)); // stores a reference_wrapper, uses LWG-2219
145-
assert(bound4("Why do you keep renaming me?") == "Peppermint says Why do you keep renaming me?");
146-
cat.name = "Cat";
147-
assert(bound4("You can't rename me anymore, Human") == "Cat says You can't rename me anymore, Human");
148-
149-
// Test movable-only types.
150-
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
151-
if (up1 && up2) {
152-
return make_unique<int>(*up1 + *up2);
153-
} else if (up1) {
154-
return make_unique<int>(*up1 * -1);
155-
} else if (up2) {
156-
return make_unique<int>(*up2 * -10);
157-
} else {
158-
return make_unique<int>(-9000);
159-
}
160-
};
161-
auto bound6 = bind_front(move(unique_lambda), make_unique<int>(34));
162-
assert(*unique_lambda(make_unique<int>(56)) == -560);
163-
assert(*move(bound6)() == 1234);
164-
auto bound7 = move(bound6);
165-
assert(*move(bound6)() == -9000);
166-
assert(*move(bound7)() == 1234);
167-
168177
// Also test GH-1292 "bind_front violates [func.require]p8" in which the return type of bind_front inadvertently
169178
// depends on the value category and/or cv-qualification of its arguments.
170179
{

tests/std/tests/P2387R3_bind_back/test.cpp

+31-27
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,9 @@ constexpr int f3(int x, int y, int z) {
2929

3030
struct Cat {
3131
string name;
32-
};
3332

34-
struct CatNoise {
35-
string noise(const string& s, const Cat& cat) const {
36-
return cat.name + " says " + s;
33+
constexpr string noise(const string& s) const {
34+
return name + " says " + s;
3735
}
3836
};
3937

@@ -94,13 +92,42 @@ constexpr bool test_constexpr() {
9492
bound1(4);
9593
assert(value == 74);
9694

95+
// Test PMFs.
96+
Cat cat{"Peppermint"};
97+
auto bound2 = bind_back(&Cat::noise, "meow");
98+
assert(bound2(cat) == "Peppermint says meow"); // call with reference
99+
auto bound3 = bind_back(&Cat::noise, "MEOW");
100+
cat.name = "Fluffy";
101+
assert(bound3(&cat) == "Fluffy says MEOW"); // call with pointer
102+
auto bound4 = bind_back(&Cat::noise, "HISS");
103+
assert(bound4(ref(cat)) == "Fluffy says HISS"); // call with reference_wrapper
104+
97105
// Test "perfect forwarding call wrapper" behavior.
98106
auto bound5 = bind_back(DetectQualifiers{});
99107
assert(bound5() == "modifiable lvalue");
100108
assert(as_const(bound5)() == "const lvalue");
101109
assert(move(bound5)() == "modifiable rvalue");
102110
assert(move(as_const(bound5))() == "const rvalue");
103111

112+
// Test movable-only types.
113+
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
114+
if (up1 && up2) {
115+
return make_unique<int>(*up1 + *up2);
116+
} else if (up1) {
117+
return make_unique<int>(*up1 * -1);
118+
} else if (up2) {
119+
return make_unique<int>(*up2 * -10);
120+
} else {
121+
return make_unique<int>(-9000);
122+
}
123+
};
124+
auto bound6 = bind_back(move(unique_lambda), make_unique<int>(34));
125+
assert(*unique_lambda(make_unique<int>(56)) == -560);
126+
assert(*move(bound6)() == 1234);
127+
auto bound7 = move(bound6);
128+
assert(*move(bound6)() == -9000);
129+
assert(*move(bound7)() == 1234);
130+
104131
// Test decay when binding.
105132
const int arr[] = {11, 22, 33};
106133
const int three = 3;
@@ -126,33 +153,10 @@ constexpr bool test_constexpr() {
126153
return true;
127154
}
128155

129-
void test_move_only_types() {
130-
// Test movable-only types.
131-
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
132-
if (up1 && up2) {
133-
return make_unique<int>(*up1 + *up2);
134-
} else if (up1) {
135-
return make_unique<int>(*up1 * -1);
136-
} else if (up2) {
137-
return make_unique<int>(*up2 * -10);
138-
} else {
139-
return make_unique<int>(-9000);
140-
}
141-
};
142-
auto bound6 = bind_back(move(unique_lambda), make_unique<int>(34));
143-
assert(*unique_lambda(make_unique<int>(56)) == -560);
144-
assert(*move(bound6)() == 1234);
145-
auto bound7 = move(bound6);
146-
assert(*move(bound6)() == -9000);
147-
assert(*move(bound7)() == 1234);
148-
}
149-
150156
int main() {
151157
assert(test_constexpr());
152158
static_assert(test_constexpr());
153159

154-
test_move_only_types();
155-
156160
// Also test GH-1292 "bind_front violates [func.require]p8" in which the return type of bind_front inadvertently
157161
// depends on the value category and/or cv-qualification of its arguments.
158162
{

0 commit comments

Comments
 (0)