meta: range iterator is an input iterator but models a random access iterator (close #927)
This commit is contained in:
@@ -38,7 +38,7 @@ public:
|
||||
meta_range_iterator() noexcept
|
||||
: it{} {}
|
||||
|
||||
meta_range_iterator(It iter) noexcept
|
||||
meta_range_iterator(const It iter) noexcept
|
||||
: it{iter} {}
|
||||
|
||||
meta_range_iterator &operator++() noexcept {
|
||||
@@ -50,26 +50,93 @@ public:
|
||||
return ++(*this), orig;
|
||||
}
|
||||
|
||||
[[nodiscard]] reference operator*() const noexcept {
|
||||
return std::make_pair(it->first, to_value(0, it->second));
|
||||
constexpr meta_range_iterator &operator--() noexcept {
|
||||
return --it, *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] pointer operator->() const noexcept {
|
||||
constexpr meta_range_iterator operator--(int) noexcept {
|
||||
meta_range_iterator orig = *this;
|
||||
return operator--(), orig;
|
||||
}
|
||||
|
||||
constexpr meta_range_iterator &operator+=(const difference_type value) noexcept {
|
||||
it += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr meta_range_iterator operator+(const difference_type value) const noexcept {
|
||||
meta_range_iterator copy = *this;
|
||||
return (copy += value);
|
||||
}
|
||||
|
||||
constexpr meta_range_iterator &operator-=(const difference_type value) noexcept {
|
||||
return (*this += -value);
|
||||
}
|
||||
|
||||
constexpr meta_range_iterator operator-(const difference_type value) const noexcept {
|
||||
return (*this + -value);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
|
||||
return {it[value].first, to_value(0, it[value].second)};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr pointer operator->() const noexcept {
|
||||
return operator*();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator==(const meta_range_iterator &other) const noexcept {
|
||||
return it == other.it;
|
||||
[[nodiscard]] constexpr reference operator*() const noexcept {
|
||||
return {it->first, to_value(0, it->second)};
|
||||
}
|
||||
|
||||
[[nodiscard]] bool operator!=(const meta_range_iterator &other) const noexcept {
|
||||
return !(*this == other);
|
||||
}
|
||||
template<typename... Args>
|
||||
friend constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
|
||||
|
||||
template<typename... Args>
|
||||
friend constexpr bool operator==(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
|
||||
|
||||
template<typename... Args>
|
||||
friend constexpr bool operator<(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept;
|
||||
|
||||
private:
|
||||
It it;
|
||||
};
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
|
||||
return lhs.it - rhs.it;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] constexpr bool operator==(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
|
||||
return lhs.it == rhs.it;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] constexpr bool operator!=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] constexpr bool operator<(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
|
||||
return lhs.it < rhs.it;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] constexpr bool operator>(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] constexpr bool operator<=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
|
||||
return !(lhs > rhs);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] constexpr bool operator>=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept {
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,7 @@ struct MetaRange: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<int>().type("int"_hs);
|
||||
entt::meta<double>().type("double"_hs);
|
||||
entt::meta<int>().type("int"_hs).data<42>("answer"_hs);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
@@ -20,25 +19,77 @@ struct MetaRange: ::testing::Test {
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaRange, Range) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto range = entt::resolve();
|
||||
auto it = range.begin();
|
||||
|
||||
ASSERT_NE(it, range.end());
|
||||
ASSERT_TRUE(it != range.end());
|
||||
ASSERT_FALSE(it == range.end());
|
||||
|
||||
ASSERT_EQ(it->second.info(), entt::resolve<int>().info());
|
||||
ASSERT_EQ((++it)->second.info(), entt::resolve("double"_hs).info());
|
||||
ASSERT_EQ((it++)->second.info(), entt::resolve<double>().info());
|
||||
|
||||
ASSERT_EQ(it, range.end());
|
||||
}
|
||||
|
||||
TEST_F(MetaRange, EmptyRange) {
|
||||
entt::meta_reset();
|
||||
auto range = entt::resolve();
|
||||
ASSERT_EQ(range.begin(), range.end());
|
||||
}
|
||||
|
||||
TEST_F(MetaRange, Iterator) {
|
||||
using namespace entt::literals;
|
||||
|
||||
using iterator = typename decltype(entt::resolve())::iterator;
|
||||
|
||||
static_assert(std::is_same_v<iterator::value_type, std::pair<entt::id_type, entt::meta_type>>);
|
||||
static_assert(std::is_same_v<iterator::pointer, entt::input_iterator_pointer<std::pair<entt::id_type, entt::meta_type>>>);
|
||||
static_assert(std::is_same_v<iterator::reference, std::pair<entt::id_type, entt::meta_type>>);
|
||||
|
||||
auto range = entt::resolve();
|
||||
|
||||
iterator end{range.begin()};
|
||||
iterator begin{};
|
||||
begin = range.end();
|
||||
std::swap(begin, end);
|
||||
|
||||
ASSERT_EQ(begin, range.begin());
|
||||
ASSERT_EQ(end, range.end());
|
||||
ASSERT_NE(begin, end);
|
||||
|
||||
ASSERT_EQ(begin++, range.begin());
|
||||
ASSERT_EQ(begin--, range.end());
|
||||
|
||||
ASSERT_EQ(begin + 1, range.end());
|
||||
ASSERT_EQ(end - 1, range.begin());
|
||||
|
||||
ASSERT_EQ(++begin, range.end());
|
||||
ASSERT_EQ(--begin, range.begin());
|
||||
|
||||
ASSERT_EQ(begin += 1, range.end());
|
||||
ASSERT_EQ(begin -= 1, range.begin());
|
||||
|
||||
ASSERT_EQ(begin + (end - begin), range.end());
|
||||
ASSERT_EQ(begin - (begin - end), range.end());
|
||||
|
||||
ASSERT_EQ(end - (end - begin), range.begin());
|
||||
ASSERT_EQ(end + (begin - end), range.begin());
|
||||
|
||||
ASSERT_EQ(begin[0u].first, range.begin()->first);
|
||||
ASSERT_EQ(begin[0u].second, (*range.begin()).second);
|
||||
|
||||
ASSERT_LT(begin, end);
|
||||
ASSERT_LE(begin, range.begin());
|
||||
|
||||
ASSERT_GT(end, begin);
|
||||
ASSERT_GE(end, range.end());
|
||||
|
||||
entt::meta<double>().type("double"_hs);
|
||||
range = entt::resolve();
|
||||
begin = range.begin();
|
||||
|
||||
ASSERT_EQ(begin[0u].first, entt::resolve<int>().info().hash());
|
||||
ASSERT_EQ(begin[1u].second, entt::resolve("double"_hs));
|
||||
}
|
||||
|
||||
TEST_F(MetaRange, DirectValue) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<int>();
|
||||
auto range = type.data();
|
||||
|
||||
ASSERT_NE(range.cbegin(), range.cend());
|
||||
|
||||
for(auto &&[id, data]: range) {
|
||||
ASSERT_EQ(id, "answer"_hs);
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 42);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user