Convert more tests into proper gtest cases

This commit is contained in:
Denis Blank 2018-02-09 03:57:12 +01:00
parent a5640a5d35
commit 5904ea06b4

View File

@ -72,7 +72,7 @@ struct all_map {
}
};
TEST(traverse_single_test, test_container_categories) {
TEST(traverse_container, categories) {
using cti::detail::traversal::container_category_of_t;
using cti::detail::traversal::container_category_tag;
@ -94,7 +94,7 @@ TEST(traverse_single_test, test_container_categories) {
"Wrong category!");
}
TEST(traverse_single_test, test_mixed_traversal) {
TEST(traverse_mixed, traversal) {
auto res =
map_pack(all_map_float{}, 0, 1.f, make_tuple(1.f, 3),
std::vector<std::vector<int>>{{1, 2}, {4, 5}},
@ -110,19 +110,19 @@ TEST(traverse_single_test, test_mixed_traversal) {
EXPECT_TRUE((res == expected));
}
TEST(traverse_single_test, test_mixed_traversal_build_regression) {
TEST(traverse_mixed, build_regression) {
// Broken build regression tests:
traverse_pack(my_mapper{}, int(0), 1.f);
map_pack(all_map{}, 0, std::vector<int>{1, 2});
}
TEST(traverse_single_test, test_mixed_traversal_container_container_map) {
TEST(traverse_mixed, container_container_map) {
// Also a regression test
auto res = map_pack(all_map{}, std::vector<std::vector<int>>{{1, 2}});
EXPECT_EQ((res[0][0]), (0));
}
TEST(traverse_single_test, test_mixed_traversal_result_tuple_mapped) {
TEST(traverse_mixed, result_tuple_mapped) {
auto res = map_pack(
my_mapper{}, 0, 1.f,
make_tuple(1.f, 3, std::vector<std::vector<int>>{{1, 2}, {4, 5}},
@ -141,7 +141,7 @@ TEST(traverse_single_test, test_mixed_traversal_result_tuple_mapped) {
EXPECT_TRUE((res == expected));
}
TEST(traverse_single_test, test_mixed_traversal_all_elements_traversed) {
TEST(traverse_mixed, all_elements_traversed) {
int count = 0;
traverse_pack(
[&](int el) {
@ -153,30 +153,6 @@ TEST(traverse_single_test, test_mixed_traversal_all_elements_traversed) {
EXPECT_EQ((count), (7));
}
/*
struct my_unwrapper {
template <typename T,
typename std::enable_if<is_future<T>::value>::type* = nullptr>
auto operator()(T future) const -> typename future_traits<T>::result_type {
return future.get();
}
};
static void test_mixed_early_unwrapping() {
{
auto res = map_pack(my_unwrapper{}, // ...
0, 1, make_ready_future(3),
make_tuple(make_ready_future(4), make_ready_future(5)));
auto expected = make_tuple(0, 1, 3, make_tuple(4, 5));
static_assert(std::is_same<decltype(res), decltype(expected)>::value,
"Type mismatch!");
EXPECT_TRUE((res == expected));
}
}
*/
template <typename T>
struct my_allocator {
using value_type = T;
@ -218,54 +194,48 @@ struct my_allocator {
}
};
void test_mixed_container_remap() {
// Traits
// Traits
TEST(traverse_mixed_container_remap, all_elements_traversed) {
// TODO Enable this
// using detail::container_remapping::has_push_back;
// EXPECT_EQ((has_push_back<std::vector<int>, int>::value), true);
// EXPECT_EQ((has_push_back<int, int>::value), false);
}
static unsigned long int_remapper(unsigned short i) {
return i - 1;
}
// Rebinds the values
TEST(traverse_rebind_allocator, maps_values) {
std::vector<unsigned short> source = {1, 2, 3};
std::vector<unsigned long> dest = map_pack(int_remapper, source);
EXPECT_TRUE((dest == decltype(dest){0, 1, 2}));
}
// Rebinds the allocator
TEST(traverse_rebind_allocator, converts_allocator) {
static unsigned const canary = 78787;
my_allocator<unsigned short> allocator(canary);
std::vector<unsigned short, my_allocator<unsigned short>> source(allocator);
// Empty
{
// TODO Enable this
// using detail::container_remapping::has_push_back;
// EXPECT_EQ((has_push_back<std::vector<int>, int>::value), true);
// EXPECT_EQ((has_push_back<int, int>::value), false);
std::vector<unsigned long, my_allocator<unsigned long>> remapped =
map_pack(int_remapper, source);
EXPECT_EQ((remapped.get_allocator().state_), (canary));
}
// Rebind
// Non empty
source.push_back(1);
{
auto const remapper = [](unsigned short i) -> unsigned long {
return i - 1;
};
std::vector<unsigned long, my_allocator<unsigned long>> remapped =
map_pack(int_remapper, source);
// Rebinds the values
{
std::vector<unsigned short> source = {1, 2, 3};
std::vector<unsigned long> dest = map_pack(remapper, source);
EXPECT_TRUE((dest == decltype(dest){0, 1, 2}));
}
// Rebinds the allocator
{
static unsigned const canary = 78787;
my_allocator<unsigned short> allocator(canary);
std::vector<unsigned short, my_allocator<unsigned short>> source(
allocator);
// Empty
{
std::vector<unsigned long, my_allocator<unsigned long>> remapped =
map_pack(remapper, source);
EXPECT_EQ((remapped.get_allocator().state_), (canary));
}
// Non empty
source.push_back(1);
{
std::vector<unsigned long, my_allocator<unsigned long>> remapped =
map_pack(remapper, source);
EXPECT_EQ((remapped.get_allocator().state_), (canary));
}
}
EXPECT_EQ((remapped.get_allocator().state_), (canary));
}
}
@ -285,7 +255,8 @@ struct my_int_mapper {
}
};
void test_mixed_fall_through() {
// TODO Take a look at this... what it was supposed to test
TEST(traverse_mixed_fall_through, misc) {
traverse_pack(my_int_mapper{}, int(0),
std::vector<tuple<float, float>>{make_tuple(1.f, 2.f)},
make_tuple(std::vector<float>{1.f, 2.f}));
@ -298,12 +269,15 @@ void test_mixed_fall_through() {
std::vector<std::vector<float>>{{1.f, 2.f}},
make_tuple(77.f, 2));
(void)res1;
auto res2 = map_pack(
[](int) {
// ...
return 0;
},
1, std::vector<int>{2, 3});
(void)res2;
}
class counter_mapper {
@ -370,276 +344,270 @@ public:
}
};
void test_strategic_traverse() {
// Every element in the pack is visited
{
int counter = 0;
counter_mapper mapper(counter);
traverse_pack(mapper, test_tag_1{}, test_tag_2{}, test_tag_3{});
EXPECT_EQ(counter, 3);
}
// Every element in the pack is visited from left to right
{
int counter = 0;
traverse_pack(
[&](int el) {
EXPECT_EQ(counter, el);
++counter;
},
0, 1, 2, 3);
EXPECT_EQ(counter, 4);
}
// Elements accepted by the mapper aren't traversed:
// - Signature
{
int counter = 0;
counter_mapper_rejecting_non_tag_1 mapper(counter);
traverse_pack(mapper, test_tag_1{}, test_tag_2{}, test_tag_3{});
EXPECT_EQ(counter, 1);
}
// - SFINAE
{
int counter = 0;
counter_mapper_rejecting_non_tag_1_sfinae mapper(counter);
traverse_pack(mapper, test_tag_1{}, test_tag_2{}, test_tag_3{});
EXPECT_EQ(counter, 1);
}
// Remapping works across values
{
tuple<int, int, int> res = map_pack([](int i) { return i + 1; }, 0, 1, 2);
auto expected = make_tuple(1, 2, 3);
EXPECT_TRUE((res == expected));
}
// Remapping works across types
{
tag_shift_mapper mapper;
tuple<float, test_tag_2, test_tag_3, test_tag_1> res =
map_pack(mapper, 1, test_tag_1{}, test_tag_2{}, test_tag_3{});
EXPECT_EQ(get<0>(res), 0.f);
}
// Remapping works with move-only objects
{
std::unique_ptr<int> p1(new int(1));
std::unique_ptr<int> p2(new int(2));
std::unique_ptr<int> p3(new int(3));
tuple<std::unique_ptr<unsigned>, std::unique_ptr<unsigned>,
std::unique_ptr<unsigned>>
res = map_pack(
// Since we pass the unique_ptr's as r-value,
// those should be passed as r-values to the mapper.
[](std::unique_ptr<int>&& ptr) {
// We explicitly move the ownership here
std::unique_ptr<int> owned = std::move(ptr);
return std::unique_ptr<unsigned>(new unsigned(*owned + 1));
},
std::move(p1), std::move(p2), std::move(p3));
// We expect the ownership of p1 - p3 to be invalid
EXPECT_TRUE((!bool(p1)));
EXPECT_TRUE((!bool(p2)));
EXPECT_TRUE((!bool(p3)));
EXPECT_EQ((*get<0>(res)), 2U);
EXPECT_EQ((*get<1>(res)), 3U);
EXPECT_EQ((*get<2>(res)), 4U);
}
// Move only types contained in a pack which was passed as l-value
// reference is forwarded to the mapper as reference too.
{
std::vector<std::unique_ptr<int>> container;
container.push_back(std::unique_ptr<int>(new int(3)));
std::vector<int> res =
map_pack([](std::unique_ptr<int>& p) { return *p; }, container);
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ(res[0], 3);
}
// Single object remapping returns the value itself without any boxing
{
int res = map_pack([](int i) { return i; }, 1);
EXPECT_EQ(res, 1);
}
// Make it possible to pass move only objects in as reference,
// while returning those as reference.
{
std::unique_ptr<int> ptr(new int(7));
std::unique_ptr<int> const& ref = map_pack(
[](std::unique_ptr<int> const& ref) -> std::unique_ptr<int> const& {
// ...
return ref;
},
ptr);
EXPECT_EQ(*ref, 7);
*ptr = 0;
EXPECT_EQ(*ref, 0);
}
// Multiple args: Make it possible to pass move only objects in
// as reference, while returning those as reference.
{
std::unique_ptr<int> ptr1(new int(6));
std::unique_ptr<int> ptr2(new int(7));
tuple<std::unique_ptr<int> const&, std::unique_ptr<int> const&> ref =
map_pack(
[](std::unique_ptr<int> const& ref) -> std::unique_ptr<int> const& {
// ...
return ref;
},
ptr1, ptr2);
EXPECT_EQ((*get<0>(ref)), 6);
EXPECT_EQ((*get<1>(ref)), 7);
*ptr1 = 1;
*ptr2 = 2;
EXPECT_EQ((*get<0>(ref)), 1);
EXPECT_EQ((*get<1>(ref)), 2);
}
// Every element in the pack is visited
TEST(traverse_strategic_traverse, visit_all_elements) {
int counter = 0;
counter_mapper mapper(counter);
traverse_pack(mapper, test_tag_1{}, test_tag_2{}, test_tag_3{});
EXPECT_EQ(counter, 3);
}
void test_strategic_container_traverse() {
// Every element in the container is visited
// - Plain container
{
int counter = 0;
counter_mapper mapper(counter);
std::vector<int> container;
container.resize(100);
traverse_pack(mapper, std::move(container));
EXPECT_EQ(counter, 100);
}
// Every element in the pack is visited from left to right
TEST(traverse_strategic_traverse, visit_left_to_right) {
int counter = 0;
traverse_pack(
[&](int el) {
EXPECT_EQ(counter, el);
++counter;
},
0, 1, 2, 3);
EXPECT_EQ(counter, 4);
}
// - Nested container
{
int counter = 0;
counter_mapper mapper(counter);
std::vector<std::vector<int>> container;
for (unsigned i = 0; i < 10; ++i) {
std::vector<int> nested;
nested.resize(10);
container.push_back(nested);
}
// Elements accepted by the mapper aren't traversed:
// - Signature
TEST(traverse_strategic_traverse, visit_non_accepted) {
int counter = 0;
counter_mapper_rejecting_non_tag_1 mapper(counter);
traverse_pack(mapper, test_tag_1{}, test_tag_2{}, test_tag_3{});
EXPECT_EQ(counter, 1);
}
traverse_pack(mapper, std::move(container));
EXPECT_EQ(counter, 100);
}
// - SFINAE
TEST(traverse_strategic_traverse, visit_not_finaed) {
int counter = 0;
counter_mapper_rejecting_non_tag_1_sfinae mapper(counter);
traverse_pack(mapper, test_tag_1{}, test_tag_2{}, test_tag_3{});
EXPECT_EQ(counter, 1);
}
// Every element in the container is visited from left to right
{
int counter = 0;
traverse_pack(
[&](int el) {
EXPECT_EQ(counter, el);
++counter;
},
std::vector<int>{0, 1}, std::vector<std::vector<int>>{{2, 3}, {4, 5}});
EXPECT_EQ(counter, 6);
}
// Remapping works across values
TEST(traverse_strategic_traverse, remap_across_values) {
tuple<int, int, int> res = map_pack([](int i) { return i + 1; }, 0, 1, 2);
// The container type itself is changed
// - Plain container
{
std::vector<int> container{1, 2, 3};
std::vector<float> res =
map_pack([](int) { return 0.f; }, std::move(container));
EXPECT_EQ(res.size(), 3U);
}
auto expected = make_tuple(1, 2, 3);
EXPECT_TRUE((res == expected));
}
// - Nested container
{
std::vector<std::vector<int>> container;
std::vector<std::vector<float>> res =
map_pack([](int) { return 0.f; }, std::move(container));
}
// Remapping works across types
TEST(traverse_strategic_traverse, remap_across_types) {
tag_shift_mapper mapper;
tuple<float, test_tag_2, test_tag_3, test_tag_1> res =
map_pack(mapper, 1, test_tag_1{}, test_tag_2{}, test_tag_3{});
// - Move only container
{
std::vector<std::unique_ptr<int>> container;
container.push_back(std::unique_ptr<int>(new int(5)));
std::vector<int> res = map_pack(
[](std::unique_ptr<int>&& ptr) { return *ptr; }, std::move(container));
EXPECT_EQ(get<0>(res), 0.f);
}
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ(res[0], 5);
}
// Remapping works with move-only objects
TEST(traverse_strategic_traverse, remap_move_only) {
std::unique_ptr<int> p1(new int(1));
std::unique_ptr<int> p2(new int(2));
std::unique_ptr<int> p3(new int(3));
// Every element in the container is remapped
// - Plain container
{
std::vector<int> container(100, 1);
auto res = map_pack([](int) { return 2; }, std::move(container));
EXPECT_TRUE(
(std::all_of(res.begin(), res.end(), [](int i) { return i == 2; })));
}
// - Nested container
{
std::vector<std::list<int>> container;
for (unsigned i = 0; i < 10; ++i) {
std::list<int> nested(10, 1);
container.push_back(nested);
}
auto res = map_pack([](int) { return 2; }, std::move(container));
EXPECT_TRUE(
(std::all_of(res.begin(), res.end(), [](std::list<int> const& nested) {
return std::all_of(nested.begin(), nested.end(),
[](int i) { return i == 2; });
})));
}
/// - Ensure correct container remapping when returning references
{
// l-value references
{
std::vector<std::unique_ptr<int>> container;
container.push_back(std::unique_ptr<int>(new int(7)));
std::vector<int> res = map_pack(
[](std::unique_ptr<int> const& ref) -> int const& {
// ...
return *ref;
tuple<std::unique_ptr<unsigned>, std::unique_ptr<unsigned>,
std::unique_ptr<unsigned>>
res = map_pack(
// Since we pass the unique_ptr's as r-value,
// those should be passed as r-values to the mapper.
[](std::unique_ptr<int>&& ptr) {
// We explicitly move the ownership here
std::unique_ptr<int> owned = std::move(ptr);
return std::unique_ptr<unsigned>(new unsigned(*owned + 1));
},
container);
std::move(p1), std::move(p2), std::move(p3));
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ(res[0], 7);
}
// We expect the ownership of p1 - p3 to be invalid
EXPECT_TRUE((!bool(p1)));
EXPECT_TRUE((!bool(p2)));
EXPECT_TRUE((!bool(p3)));
// r-value references
{
std::vector<std::unique_ptr<std::unique_ptr<int>>> container;
container.push_back(std::unique_ptr<std::unique_ptr<int>>(
new std::unique_ptr<int>(new int(7))));
EXPECT_EQ((*get<0>(res)), 2U);
EXPECT_EQ((*get<1>(res)), 3U);
EXPECT_EQ((*get<2>(res)), 4U);
}
std::vector<std::unique_ptr<int>> res = map_pack(
[](std::unique_ptr<std::unique_ptr<int>> &
ref) -> std::unique_ptr<int>&& {
// Move only types contained in a pack which was passed as l-value
// reference is forwarded to the mapper as reference too.
TEST(traverse_strategic_traverse, remap_references) {
std::vector<std::unique_ptr<int>> container;
container.push_back(std::unique_ptr<int>(new int(3)));
std::vector<int> res =
map_pack([](std::unique_ptr<int>& p) { return *p; }, container);
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ(res[0], 3);
}
// Single object remapping returns the value itself without any boxing
TEST(traverse_strategic_traverse, remap_single_values) {
int res = map_pack([](int i) { return i; }, 1);
EXPECT_EQ(res, 1);
}
// Make it possible to pass move only objects in as reference,
// while returning those as reference.
TEST(traverse_strategic_traverse, remap_move_only_as_ref) {
std::unique_ptr<int> ptr(new int(7));
std::unique_ptr<int> const& ref = map_pack(
[](std::unique_ptr<int> const& ref) -> std::unique_ptr<int> const& {
// ...
return ref;
},
ptr);
EXPECT_EQ(*ref, 7);
*ptr = 0;
EXPECT_EQ(*ref, 0);
}
// Multiple args: Make it possible to pass move only objects in
// as reference, while returning those as reference.
TEST(traverse_strategic_traverse, remap_multiple_move_only_as_ref) {
std::unique_ptr<int> ptr1(new int(6));
std::unique_ptr<int> ptr2(new int(7));
tuple<std::unique_ptr<int> const&, std::unique_ptr<int> const&> ref =
map_pack(
[](std::unique_ptr<int> const& ref) -> std::unique_ptr<int> const& {
// ...
return std::move(*ref);
return ref;
},
container);
ptr1, ptr2);
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ((*res[0]), 7);
}
EXPECT_EQ((*get<0>(ref)), 6);
EXPECT_EQ((*get<1>(ref)), 7);
*ptr1 = 1;
*ptr2 = 2;
EXPECT_EQ((*get<0>(ref)), 1);
EXPECT_EQ((*get<1>(ref)), 2);
}
// Every element in the container is visited
// - Plain container
TEST(test_strategic_container_traverse, plain_container) {
int counter = 0;
counter_mapper mapper(counter);
std::vector<int> container;
container.resize(100);
traverse_pack(mapper, std::move(container));
EXPECT_EQ(counter, 100);
}
// - Nested container
TEST(test_strategic_container_traverse, nested_container) {
int counter = 0;
counter_mapper mapper(counter);
std::vector<std::vector<int>> container;
for (unsigned i = 0; i < 10; ++i) {
std::vector<int> nested;
nested.resize(10);
container.push_back(nested);
}
traverse_pack(mapper, std::move(container));
EXPECT_EQ(counter, 100);
}
// Every element in the container is visited from left to right
TEST(test_strategic_container_traverse, left_to_right) {
int counter = 0;
traverse_pack(
[&](int el) {
EXPECT_EQ(counter, el);
++counter;
},
std::vector<int>{0, 1}, std::vector<std::vector<int>>{{2, 3}, {4, 5}});
EXPECT_EQ(counter, 6);
}
// The container type itself is changed
// - Plain container
TEST(test_strategic_container_traverse, type_changed_plain) {
std::vector<int> container{1, 2, 3};
std::vector<float> res =
map_pack([](int) { return 0.f; }, std::move(container));
EXPECT_EQ(res.size(), 3U);
}
// - Nested container
TEST(test_strategic_container_traverse, type_changed_nested) {
std::vector<std::vector<int>> container;
std::vector<std::vector<float>> res =
map_pack([](int) { return 0.f; }, std::move(container));
}
// - Move only container
TEST(test_strategic_container_traverse, type_changed_move_only) {
std::vector<std::unique_ptr<int>> container;
container.push_back(std::unique_ptr<int>(new int(5)));
std::vector<int> res = map_pack(
[](std::unique_ptr<int>&& ptr) { return *ptr; }, std::move(container));
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ(res[0], 5);
}
// Every element in the container is remapped
// - Plain container
TEST(test_strategic_container_traverse, every_element_remapped_plain) {
std::vector<int> container(100, 1);
auto res = map_pack([](int) { return 2; }, std::move(container));
EXPECT_TRUE(
(std::all_of(res.begin(), res.end(), [](int i) { return i == 2; })));
}
// - Nested container
TEST(test_strategic_container_traverse, every_element_remapped_nested) {
std::vector<std::list<int>> container;
for (unsigned i = 0; i < 10; ++i) {
std::list<int> nested(10, 1);
container.push_back(nested);
}
auto res = map_pack([](int) { return 2; }, std::move(container));
EXPECT_TRUE(
(std::all_of(res.begin(), res.end(), [](std::list<int> const& nested) {
return std::all_of(nested.begin(), nested.end(),
[](int i) { return i == 2; });
})));
}
/// - Ensure correct container remapping when returning references
// l-value references
TEST(test_strategic_container_traverse, every_element_remapped_lvalue) {
std::vector<std::unique_ptr<int>> container;
container.push_back(std::unique_ptr<int>(new int(7)));
std::vector<int> res = map_pack(
[](std::unique_ptr<int> const& ref) -> int const& {
// ...
return *ref;
},
container);
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ(res[0], 7);
}
// r-value references
TEST(test_strategic_container_traverse, every_element_remapped_rvalue) {
std::vector<std::unique_ptr<std::unique_ptr<int>>> container;
container.push_back(std::unique_ptr<std::unique_ptr<int>>(
new std::unique_ptr<int>(new int(7))));
std::vector<std::unique_ptr<int>> res = map_pack(
[](std::unique_ptr<std::unique_ptr<int>> &
ref) -> std::unique_ptr<int>&& {
// ...
return std::move(*ref);
},
container);
EXPECT_EQ(res.size(), 1U);
EXPECT_EQ((*res[0]), 7);
}
TEST(traverse_single_test, test_strategic_tuple_like_traverse_homogeneous) {
@ -650,70 +618,68 @@ TEST(traverse_single_test, test_strategic_tuple_like_traverse_homogeneous) {
EXPECT_TRUE((res == std::array<float, 3>{{1.f, 1.f, 1.f}}));
}
void test_strategic_tuple_like_traverse() {
// Every element in the tuple like type is visited
{
int counter = 0;
counter_mapper mapper(counter);
traverse_pack(mapper, make_tuple(test_tag_1{}, test_tag_2{}, test_tag_3{}));
EXPECT_EQ(counter, 3);
}
// Every element in the tuple like type is visited
TEST(traverse_strategic_tuple_like_traverse, all_elements_visited) {
int counter = 0;
counter_mapper mapper(counter);
traverse_pack(mapper, make_tuple(test_tag_1{}, test_tag_2{}, test_tag_3{}));
EXPECT_EQ(counter, 3);
}
// Every element in the tuple like type is visited from left to right
{
int counter = 0;
traverse_pack(
[&](int el) {
EXPECT_EQ(counter, el);
++counter;
},
make_tuple(0, 1), make_tuple(make_tuple(2, 3), make_tuple(4, 5)),
make_tuple(make_tuple(make_tuple(6, 7))));
EXPECT_EQ(counter, 8);
}
// Every element in the tuple like type is visited from left to right
TEST(traverse_strategic_tuple_like_traverse, visited_left_to_right) {
int counter = 0;
traverse_pack(
[&](int el) {
EXPECT_EQ(counter, el);
++counter;
},
make_tuple(0, 1), make_tuple(make_tuple(2, 3), make_tuple(4, 5)),
make_tuple(make_tuple(make_tuple(6, 7))));
EXPECT_EQ(counter, 8);
}
// The container tuple like type itself is changed
{
tag_shift_mapper mapper;
tuple<float, test_tag_2, test_tag_3, test_tag_1> res = map_pack(
mapper, make_tuple(1, test_tag_1{}, test_tag_2{}, test_tag_3{}));
// The container tuple like type itself is changed
TEST(traverse_strategic_tuple_like_traverse, type_is_remapped) {
tag_shift_mapper mapper;
tuple<float, test_tag_2, test_tag_3, test_tag_1> res =
map_pack(mapper, make_tuple(1, test_tag_1{}, test_tag_2{}, test_tag_3{}));
EXPECT_EQ(get<0>(res), 0.f);
}
EXPECT_EQ(get<0>(res), 0.f);
}
// Every element in the tuple like type is remapped
{
tuple<float, float, float> res =
map_pack([](int) { return 1.f; }, make_tuple(0, 0, 0));
// Every element in the tuple like type is remapped
TEST(traverse_strategic_tuple_like_traverse, all_elements_remapped) {
tuple<float, float, float> res =
map_pack([](int) { return 1.f; }, make_tuple(0, 0, 0));
auto expected = make_tuple(1.f, 1.f, 1.f);
auto expected = make_tuple(1.f, 1.f, 1.f);
static_assert(std::is_same<decltype(res), decltype(expected)>::value,
"Type mismatch!");
EXPECT_TRUE((res == expected));
}
static_assert(std::is_same<decltype(res), decltype(expected)>::value,
"Type mismatch!");
EXPECT_TRUE((res == expected));
}
// Make it possible to pass tuples containing move only objects
// in as reference, while returning those as reference.
{
auto value = make_tuple(std::unique_ptr<int>(new int(6)),
std::unique_ptr<int>(new int(7)));
// Make it possible to pass tuples containing move only objects
// in as reference, while returning those as reference.
TEST(traverse_strategic_tuple_like_traverse, remap_references) {
auto value = make_tuple(std::unique_ptr<int>(new int(6)),
std::unique_ptr<int>(new int(7)));
tuple<std::unique_ptr<int> const&, std::unique_ptr<int> const&> ref =
map_pack(
[](std::unique_ptr<int> const& ref) -> std::unique_ptr<int> const& {
// ...
return ref;
},
value);
tuple<std::unique_ptr<int> const&, std::unique_ptr<int> const&> ref =
map_pack(
[](std::unique_ptr<int> const& ref) -> std::unique_ptr<int> const& {
// ...
return ref;
},
value);
EXPECT_EQ((*get<0>(ref)), 6);
EXPECT_EQ((*get<1>(ref)), 7);
(*get<0>(ref)) = 1;
(*get<1>(ref)) = 2;
EXPECT_EQ((*get<0>(ref)), 1);
EXPECT_EQ((*get<1>(ref)), 2);
}
EXPECT_EQ((*get<0>(ref)), 6);
EXPECT_EQ((*get<1>(ref)), 7);
(*get<0>(ref)) = 1;
(*get<1>(ref)) = 2;
EXPECT_EQ((*get<0>(ref)), 1);
EXPECT_EQ((*get<1>(ref)), 2);
}
/// A mapper which duplicates the given element
@ -732,44 +698,40 @@ struct zero_mapper {
}
};
void test_spread_traverse() {
// 1:2 mappings (multiple arguments)
{
tuple<int, int, int, int> res = map_pack(duplicate_mapper{}, 1, 2);
// 1:2 mappings (multiple arguments)
TEST(traverse_spread_traverse, one_to_two_mapping) {
tuple<int, int, int, int> res = map_pack(duplicate_mapper{}, 1, 2);
auto expected = make_tuple(1, 1, 2, 2);
auto expected = make_tuple(1, 1, 2, 2);
EXPECT_TRUE((res == expected));
}
// 1:0 mappings
{
using Result = decltype(map_pack(zero_mapper{}, 0, 1, 2));
static_assert(std::is_void<Result>::value, "Failed...");
}
EXPECT_TRUE((res == expected));
}
void test_spread_container_traverse() {
// 1:2 mappings (multiple arguments)
{
std::vector<tuple<int, int>> res =
map_pack(duplicate_mapper{}, std::vector<int>{1});
std::vector<tuple<int, int>> expected;
expected.push_back(make_tuple(1, 1));
EXPECT_TRUE((res == expected));
}
// 1:0 mappings
{
using Result = decltype(map_pack(zero_mapper{}, std::vector<int>{1}));
static_assert(std::is_void<Result>::value, "Failed...");
}
// 1:0 mappings
TEST(traverse_spread_traverse, one_to_zero_mapping) {
using Result = decltype(map_pack(zero_mapper{}, 0, 1, 2));
static_assert(std::is_void<Result>::value, "Failed...");
}
// 1:2 mappings (multiple arguments)
TEST(traverse_single_test, test_spread_container_traverse_multiple_args) {
TEST(traverse_spread_container_traverse, one_to_two_mapping) {
std::vector<tuple<int, int>> res =
map_pack(duplicate_mapper{}, std::vector<int>{1});
std::vector<tuple<int, int>> expected;
expected.push_back(make_tuple(1, 1));
EXPECT_TRUE((res == expected));
}
// 1:0 mappings
TEST(traverse_spread_container_traverse, one_to_zero_mapping) {
using Result = decltype(map_pack(zero_mapper{}, std::vector<int>{1}));
static_assert(std::is_void<Result>::value, "Failed...");
}
// 1:2 mappings (multiple arguments)
TEST(traverse_spread_container_traverse, multiple_args) {
auto res = map_pack(duplicate_mapper{}, std::array<int, 2>{{1, 2}});
std::array<int, 4> expected{{1, 1, 2, 2}};
@ -777,29 +739,26 @@ TEST(traverse_single_test, test_spread_container_traverse_multiple_args) {
EXPECT_TRUE((res == expected));
}
void test_spread_tuple_like_traverse() {
// 1:2 mappings (multiple arguments)
{
tuple<tuple<int, int, int, int>> res =
map_pack(duplicate_mapper{}, make_tuple(make_tuple(1, 2)));
// 1:2 mappings (multiple arguments)
TEST(traverse_spread_tuple_like_traverse, multiple_args) {
tuple<tuple<int, int, int, int>> res =
map_pack(duplicate_mapper{}, make_tuple(make_tuple(1, 2)));
tuple<tuple<int, int, int, int>> expected =
make_tuple(make_tuple(1, 1, 2, 2));
tuple<tuple<int, int, int, int>> expected =
make_tuple(make_tuple(1, 1, 2, 2));
EXPECT_TRUE((res == expected));
}
// 1:0 mappings
{
using Result =
decltype(map_pack(zero_mapper{}, make_tuple(make_tuple(1, 2), 1), 1));
static_assert(std::is_void<Result>::value, "Failed...");
}
// 1:0 mappings
{
using Result =
decltype(map_pack(zero_mapper{}, std::array<int, 2>{{1, 2}}));
static_assert(std::is_void<Result>::value, "Failed...");
}
EXPECT_TRUE((res == expected));
}
// 1:0 mappings
TEST(traverse_spread_tuple_like_traverse, one_to_zero_mapping_tuple) {
using Result =
decltype(map_pack(zero_mapper{}, make_tuple(make_tuple(1, 2), 1), 1));
static_assert(std::is_void<Result>::value, "Failed...");
}
// 1:0 mappings
TEST(traverse_spread_tuple_like_traverse, one_to_zero_mapping_array) {
using Result = decltype(map_pack(zero_mapper{}, std::array<int, 2>{{1, 2}}));
static_assert(std::is_void<Result>::value, "Failed...");
}