/* * Ported from folly/container/test/EnumerateTest.cpp */ #include #include #include namespace { template struct IsConstReference { constexpr static bool value = false; }; template struct IsConstReference { constexpr static bool value = true; }; constexpr int basicSum(const std::array& test) { int sum = 0; for (auto it : c10::enumerate(test)) { sum += *it; } return sum; } constexpr int cpp17StructuredBindingSum(const std::array& test) { int sum = 0; for (auto&& [_, integer] : c10::enumerate(test)) { sum += integer; } return sum; } } // namespace TEST(Enumerate, Basic) { std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (auto it : c10::enumerate(v)) { EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); /* Test mutability. */ std::string newValue = "x"; *it = newValue; EXPECT_EQ(newValue, v[i]); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, BasicRRef) { std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (auto&& it : c10::enumerate(v)) { EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); /* Test mutability. */ std::string newValue = "x"; *it = newValue; EXPECT_EQ(newValue, v[i]); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, BasicConst) { std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (const auto it : c10::enumerate(v)) { static_assert(IsConstReference::value, "Const enumeration"); EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, BasicConstRef) { std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (const auto& it : c10::enumerate(v)) { static_assert(IsConstReference::value, "Const enumeration"); EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, BasicConstRRef) { std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (const auto&& it : c10::enumerate(v)) { static_assert(IsConstReference::value, "Const enumeration"); EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, BasicVecBool) { std::vector v = {true, false, false, true}; size_t i = 0; for (auto it : c10::enumerate(v)) { EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, BasicVecBoolRRef) { std::vector v = {true, false, false, true}; size_t i = 0; for (auto it : c10::enumerate(v)) { EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, Temporary) { std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (auto&& it : c10::enumerate(decltype(v)(v))) { // Copy v. EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, BasicConstArg) { const std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (auto&& it : c10::enumerate(v)) { static_assert( IsConstReference::value, "Enumerating a const vector"); EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, TemporaryConstEnumerate) { std::vector v = {"abc", "a", "ab"}; size_t i = 0; for (const auto&& it : c10::enumerate(decltype(v)(v))) { // Copy v. static_assert(IsConstReference::value, "Const enumeration"); EXPECT_EQ(it.index, i); EXPECT_EQ(*it, v[i]); EXPECT_EQ(it->size(), v[i].size()); ++i; } EXPECT_EQ(i, v.size()); } TEST(Enumerate, EmptyRange) { std::vector v; for (auto&& it : c10::enumerate(v)) { (void)it; // Silence warnings. ADD_FAILURE(); } } class CStringRange { const char* cstr; public: struct Sentinel {}; explicit CStringRange(const char* cstr_) : cstr(cstr_) {} const char* begin() const { return cstr; } Sentinel end() const { return Sentinel{}; } }; static bool operator==(const char* c, CStringRange::Sentinel) { return *c == 0; } TEST(Enumerate, Cpp17Support) { std::array test = {"test"}; for (const auto&& it : c10::enumerate(CStringRange{test.data()})) { ASSERT_LT(it.index, test.size()); EXPECT_EQ(*it, test[it.index]); } } TEST(Enumerate, Cpp17StructuredBindingConstRef) { std::vector test = {"abc", "a", "ab"}; for (const auto& [index, str] : c10::enumerate(test)) { ASSERT_LT(index, test.size()); EXPECT_EQ(str, test[index]); } } TEST(Enumerate, Cpp17StructuredBindingConstRRef) { std::vector test = {"abc", "a", "ab"}; for (const auto&& [index, str] : c10::enumerate(test)) { ASSERT_LT(index, test.size()); EXPECT_EQ(str, test[index]); } } TEST(Enumerate, Cpp17StructuredBindingConstVector) { const std::vector test = {"abc", "a", "ab"}; for (auto&& [index, str] : c10::enumerate(test)) { static_assert( IsConstReference::value, "Enumerating const vector"); ASSERT_LT(index, test.size()); EXPECT_EQ(str, test[index]); } } TEST(Enumerate, Cpp17StructuredBindingModify) { std::vector test = {1, 2, 3, 4, 5}; for (auto&& [index, integer] : c10::enumerate(test)) { integer = 0; } for (const auto& integer : test) { EXPECT_EQ(integer, 0); } } TEST(Enumerate, BasicConstexpr) { constexpr std::array test = {1, 2, 3}; static_assert(basicSum(test) == 6, "Basic enumerating is not constexpr"); EXPECT_EQ(basicSum(test), 6); } TEST(Enumerate, Cpp17StructuredBindingConstexpr) { constexpr std::array test = {1, 2, 3}; static_assert( cpp17StructuredBindingSum(test) == 6, "C++17 structured binding enumerating is not constexpr"); EXPECT_EQ(cpp17StructuredBindingSum(test), 6); }