#include #include using namespace c10::guts; namespace { namespace test_function_traits { static_assert(std::is_same::return_type>::value, ""); static_assert(std::is_same::return_type>::value, ""); static_assert(std::is_same, typename function_traits::parameter_types>::value, ""); static_assert(std::is_same, typename function_traits::parameter_types>::value, ""); } struct MovableOnly { constexpr MovableOnly(int val_): val(val_) {/* no default constructor */} MovableOnly(const MovableOnly&) = delete; MovableOnly(MovableOnly&&) = default; MovableOnly& operator=(const MovableOnly&) = delete; MovableOnly& operator=(MovableOnly&&) = default; friend bool operator==(const MovableOnly& lhs, const MovableOnly& rhs) {return lhs.val == rhs.val;} private: int val; }; template using is_my_movable_only_class = std::is_same>>; struct CopyCounting { int move_count; int copy_count; CopyCounting(): move_count(0), copy_count(0) {} CopyCounting(const CopyCounting& rhs): move_count(rhs.move_count), copy_count(rhs.copy_count + 1) {} CopyCounting(CopyCounting&& rhs): move_count(rhs.move_count + 1), copy_count(rhs.copy_count) {} CopyCounting& operator=(const CopyCounting& rhs) { move_count = rhs.move_count; copy_count = rhs.copy_count + 1; return *this; } CopyCounting& operator=(CopyCounting&& rhs) { move_count = rhs.move_count + 1; copy_count = rhs.copy_count; return *this; } }; template using is_my_copy_counting_class = std::is_same>>; namespace test_extract_arg_by_filtered_index { class MyClass {}; TEST(MetaprogrammingTest, ExtractArgByFilteredIndex) { auto a1 = extract_arg_by_filtered_index(3, "bla", MyClass(), 4, nullptr, 5); auto a2 = extract_arg_by_filtered_index(3, "bla", MyClass(), 4, nullptr, 5); auto a3 = extract_arg_by_filtered_index(3, "bla", MyClass(), 4, nullptr, 5); EXPECT_EQ(3, a1); EXPECT_EQ(4, a2); EXPECT_EQ(5, a3); } TEST(MetaprogrammingTest, ExtractArgByFilteredIndex_singleInput) { auto a1 = extract_arg_by_filtered_index(3); EXPECT_EQ(3, a1); } TEST(MetaprogrammingTest, ExtractArgByFilteredIndex_movableOnly) { MovableOnly a1 = extract_arg_by_filtered_index(3, MovableOnly(3), "test", MovableOnly(1)); MovableOnly a2 = extract_arg_by_filtered_index(3, MovableOnly(3), "test", MovableOnly(1)); EXPECT_EQ(MovableOnly(3), a1); EXPECT_EQ(MovableOnly(1), a2); } TEST(MetaprogrammingTest, ExtractArgByFilteredIndex_onlyCopiesIfNecessary) { CopyCounting source; CopyCounting source2; CopyCounting a1 = extract_arg_by_filtered_index(3, CopyCounting(), "test", source, std::move(source2)); CopyCounting a2 = extract_arg_by_filtered_index(3, CopyCounting(), "test", source, std::move(source2)); CopyCounting a3 = extract_arg_by_filtered_index(3, CopyCounting(), "test", source, std::move(source2)); EXPECT_EQ(1, a1.move_count); EXPECT_EQ(0, a1.copy_count); EXPECT_EQ(0, a2.move_count); EXPECT_EQ(1, a3.move_count); EXPECT_EQ(0, a3.copy_count); EXPECT_EQ(1, a2.copy_count); } TEST(MetaprogrammingTest, ExtractArgByFilteredIndex_onlyMovesIfNecessary) { CopyCounting source; CopyCounting source2; CopyCounting&& a1 = extract_arg_by_filtered_index(3, std::move(source), "test", std::move(source2)); CopyCounting a2 = extract_arg_by_filtered_index(3, std::move(source), "test", std::move(source2)); EXPECT_EQ(0, a1.move_count); EXPECT_EQ(0, a1.copy_count); EXPECT_EQ(1, a2.move_count); EXPECT_EQ(0, a2.copy_count); } template using is_true = std::true_type; TEST(MetaprogrammingTest, ExtractArgByFilteredIndex_keepsLValueReferencesIntact) { MyClass obj; MyClass& a1 = extract_arg_by_filtered_index(3, obj, "test", obj); EXPECT_EQ(&obj, &a1); } } namespace test_filter_map { class MyClass {}; struct map_to_double { template constexpr double operator()(T a) const { return static_cast(a); } }; TEST(MetaprogrammingTest, FilterMap) { auto result = filter_map(map_to_double(), 3, "bla", MyClass(), 4, nullptr, 5); static_assert(std::is_same, decltype(result)>::value, ""); constexpr array expected{{3.0, 4.0, 5.0}}; EXPECT_EQ(expected, result); } TEST(MetaprogrammingTest, FilterMap_emptyInput) { auto result = filter_map(map_to_double()); static_assert(std::is_same, decltype(result)>::value, ""); constexpr array expected{{}}; EXPECT_EQ(expected, result); } TEST(MetaprogrammingTest, FilterMap_emptyOutput) { auto result = filter_map(map_to_double(), "bla", MyClass(), nullptr); static_assert(std::is_same, decltype(result)>::value, ""); constexpr array expected{{}}; EXPECT_EQ(expected, result); } TEST(MetaprogrammingTest, FilterMap_movableOnly_byRValue) { struct map_movable_by_rvalue { MovableOnly operator()(MovableOnly&& a) const { return std::move(a); } }; auto result = filter_map(map_movable_by_rvalue(), MovableOnly(5), "bla", nullptr, 3, MovableOnly(2)); static_assert(std::is_same, decltype(result)>::value, ""); constexpr array expected {{MovableOnly(5), MovableOnly(2)}}; EXPECT_EQ(expected, result); } TEST(MetaprogrammingTest, FilterMap_movableOnly_byValue) { struct map_movable_by_lvalue { MovableOnly operator()(MovableOnly a) const { return a; } }; auto result = filter_map(map_movable_by_lvalue(), MovableOnly(5), "bla", nullptr, 3, MovableOnly(2)); static_assert(std::is_same, decltype(result)>::value, ""); constexpr array expected {{MovableOnly(5), MovableOnly(2)}}; EXPECT_EQ(expected, result); } TEST(MetaprogrammingTest, FilterMap_onlyCopiesIfNecessary) { struct map_copy_counting_by_copy { CopyCounting operator()(CopyCounting v) const { return v; } }; CopyCounting source; CopyCounting source2; auto result = filter_map(map_copy_counting_by_copy(), CopyCounting(), "bla", nullptr, 3, source, std::move(source2)); static_assert(std::is_same, decltype(result)>::value, ""); EXPECT_EQ(0, result[0].copy_count); EXPECT_EQ(2, result[0].move_count); EXPECT_EQ(1, result[1].copy_count); EXPECT_EQ(1, result[1].move_count); EXPECT_EQ(0, result[2].copy_count); EXPECT_EQ(2, result[2].move_count); } TEST(MetaprogrammingTest, FilterMap_onlyMovesIfNecessary_1) { struct map_copy_counting_by_move { CopyCounting operator()(CopyCounting&& v) const { return std::move(v); } }; CopyCounting source; auto result = filter_map(map_copy_counting_by_move(), CopyCounting(), "bla", nullptr, 3, std::move(source)); static_assert(std::is_same, decltype(result)>::value, ""); EXPECT_EQ(0, result[0].copy_count); EXPECT_EQ(1, result[0].move_count); EXPECT_EQ(0, result[1].copy_count); EXPECT_EQ(1, result[1].move_count); } TEST(MetaprogrammingTest, FilterMap_onlyMovesIfNecessary_2) { struct map_copy_counting_by_pointer { const CopyCounting* operator()(const CopyCounting& v) const { return &v; } }; CopyCounting source1; CopyCounting source2; auto result = filter_map(map_copy_counting_by_pointer(), "bla", nullptr, 3, source1, std::move(source2)); static_assert(std::is_same, decltype(result)>::value, ""); EXPECT_EQ(0, result[0]->copy_count); EXPECT_EQ(0, result[0]->move_count); EXPECT_EQ(0, result[1]->copy_count); EXPECT_EQ(0, result[1]->move_count); } } }