Skip to content

Commit

Permalink
Constexprize bind_front and bind_back tests (microsoft#3117)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
2 people authored and CaseyCarter committed Oct 6, 2022
1 parent c0a72b8 commit 9945328
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 65 deletions.
85 changes: 47 additions & 38 deletions tests/std/tests/P0356R5_bind_front/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ constexpr int f3(int x, int y, int z) {
struct Cat {
string name;

string noise(const string& s) const {
constexpr string noise(const string& s) const {
return name + " says " + s;
}
};
Expand All @@ -53,6 +53,26 @@ struct DetectQualifiers {
}
};

_CONSTEXPR23 void test_movable_only_types() {
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
if (up1 && up2) {
return make_unique<int>(*up1 + *up2);
} else if (up1) {
return make_unique<int>(*up1 * -1);
} else if (up2) {
return make_unique<int>(*up2 * -10);
} else {
return make_unique<int>(-9000);
}
};
auto bound6 = bind_front(move(unique_lambda), make_unique<int>(34));
assert(*unique_lambda(make_unique<int>(56)) == -560);
assert(*move(bound6)() == 1234);
auto bound7 = move(bound6);
assert(*move(bound6)() == -9000);
assert(*move(bound7)() == 1234);
}

constexpr bool test_constexpr() {
// Test varying numbers of arguments.
assert(bind_front(f0)() == 1729);
Expand Down Expand Up @@ -92,13 +112,39 @@ constexpr bool test_constexpr() {
bound1(4);
assert(value == 234);

// Test PMFs.
Cat cat{"Peppermint"};
auto bound2 = bind_front(&Cat::noise, cat); // stores a copy
assert(bound2("meow") == "Peppermint says meow");
cat.name = "Fluffy";
assert(cat.noise("hiss") == "Fluffy says hiss");
assert(bound2("purr") == "Peppermint says purr");

auto bound3 = bind_front(&Cat::noise, &cat); // stores a pointer
assert(bound3("MEOW") == "Fluffy says MEOW");
cat.name = "Peppermint";
assert(bound3("PURR") == "Peppermint says PURR");

auto bound4 = bind_front(&Cat::noise, ref(cat)); // stores a reference_wrapper
assert(bound4("Why do you keep renaming me?") == "Peppermint says Why do you keep renaming me?");
cat.name = "Cat";
assert(bound4("You can't rename me anymore, Human") == "Cat says You can't rename me anymore, Human");

// Test "perfect forwarding call wrapper" behavior.
auto bound5 = bind_front(DetectQualifiers{});
assert(bound5() == "modifiable lvalue");
assert(as_const(bound5)() == "const lvalue");
assert(move(bound5)() == "modifiable rvalue");
assert(move(as_const(bound5))() == "const rvalue");

#if _HAS_CXX23
test_movable_only_types();
#else // _HAS_CXX23
if (!is_constant_evaluated()) {
test_movable_only_types();
}
#endif // _HAS_CXX23

// Test decay when binding.
const int arr[] = {11, 22, 33};
const int three = 3;
Expand Down Expand Up @@ -128,43 +174,6 @@ int main() {
assert(test_constexpr());
static_assert(test_constexpr());

// Test PMFs.
Cat cat{"Peppermint"};
auto bound2 = bind_front(&Cat::noise, cat); // stores a copy
assert(bound2("meow") == "Peppermint says meow");
cat.name = "Fluffy";
assert(cat.noise("hiss") == "Fluffy says hiss");
assert(bound2("purr") == "Peppermint says purr");

auto bound3 = bind_front(&Cat::noise, &cat); // stores a pointer
assert(bound3("MEOW") == "Fluffy says MEOW");
cat.name = "Peppermint";
assert(bound3("PURR") == "Peppermint says PURR");

auto bound4 = bind_front(&Cat::noise, ref(cat)); // stores a reference_wrapper, uses LWG-2219
assert(bound4("Why do you keep renaming me?") == "Peppermint says Why do you keep renaming me?");
cat.name = "Cat";
assert(bound4("You can't rename me anymore, Human") == "Cat says You can't rename me anymore, Human");

// Test movable-only types.
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
if (up1 && up2) {
return make_unique<int>(*up1 + *up2);
} else if (up1) {
return make_unique<int>(*up1 * -1);
} else if (up2) {
return make_unique<int>(*up2 * -10);
} else {
return make_unique<int>(-9000);
}
};
auto bound6 = bind_front(move(unique_lambda), make_unique<int>(34));
assert(*unique_lambda(make_unique<int>(56)) == -560);
assert(*move(bound6)() == 1234);
auto bound7 = move(bound6);
assert(*move(bound6)() == -9000);
assert(*move(bound7)() == 1234);

// Also test GH-1292 "bind_front violates [func.require]p8" in which the return type of bind_front inadvertently
// depends on the value category and/or cv-qualification of its arguments.
{
Expand Down
58 changes: 31 additions & 27 deletions tests/std/tests/P2387R3_bind_back/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ constexpr int f3(int x, int y, int z) {

struct Cat {
string name;
};

struct CatNoise {
string noise(const string& s, const Cat& cat) const {
return cat.name + " says " + s;
constexpr string noise(const string& s) const {
return name + " says " + s;
}
};

Expand Down Expand Up @@ -94,13 +92,42 @@ constexpr bool test_constexpr() {
bound1(4);
assert(value == 74);

// Test PMFs.
Cat cat{"Peppermint"};
auto bound2 = bind_back(&Cat::noise, "meow");
assert(bound2(cat) == "Peppermint says meow"); // call with reference
auto bound3 = bind_back(&Cat::noise, "MEOW");
cat.name = "Fluffy";
assert(bound3(&cat) == "Fluffy says MEOW"); // call with pointer
auto bound4 = bind_back(&Cat::noise, "HISS");
assert(bound4(ref(cat)) == "Fluffy says HISS"); // call with reference_wrapper

// Test "perfect forwarding call wrapper" behavior.
auto bound5 = bind_back(DetectQualifiers{});
assert(bound5() == "modifiable lvalue");
assert(as_const(bound5)() == "const lvalue");
assert(move(bound5)() == "modifiable rvalue");
assert(move(as_const(bound5))() == "const rvalue");

// Test movable-only types.
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
if (up1 && up2) {
return make_unique<int>(*up1 + *up2);
} else if (up1) {
return make_unique<int>(*up1 * -1);
} else if (up2) {
return make_unique<int>(*up2 * -10);
} else {
return make_unique<int>(-9000);
}
};
auto bound6 = bind_back(move(unique_lambda), make_unique<int>(34));
assert(*unique_lambda(make_unique<int>(56)) == -560);
assert(*move(bound6)() == 1234);
auto bound7 = move(bound6);
assert(*move(bound6)() == -9000);
assert(*move(bound7)() == 1234);

// Test decay when binding.
const int arr[] = {11, 22, 33};
const int three = 3;
Expand All @@ -126,33 +153,10 @@ constexpr bool test_constexpr() {
return true;
}

void test_move_only_types() {
// Test movable-only types.
auto unique_lambda = [up1 = make_unique<int>(1200)](unique_ptr<int>&& up2) {
if (up1 && up2) {
return make_unique<int>(*up1 + *up2);
} else if (up1) {
return make_unique<int>(*up1 * -1);
} else if (up2) {
return make_unique<int>(*up2 * -10);
} else {
return make_unique<int>(-9000);
}
};
auto bound6 = bind_back(move(unique_lambda), make_unique<int>(34));
assert(*unique_lambda(make_unique<int>(56)) == -560);
assert(*move(bound6)() == 1234);
auto bound7 = move(bound6);
assert(*move(bound6)() == -9000);
assert(*move(bound7)() == 1234);
}

int main() {
assert(test_constexpr());
static_assert(test_constexpr());

test_move_only_types();

// Also test GH-1292 "bind_front violates [func.require]p8" in which the return type of bind_front inadvertently
// depends on the value category and/or cv-qualification of its arguments.
{
Expand Down

0 comments on commit 9945328

Please sign in to comment.