Skip to content

Commit

Permalink
Merge pull request #238 from arximboldi/add-identity-api
Browse files Browse the repository at this point in the history
Add identity API
  • Loading branch information
arximboldi authored Nov 22, 2022
2 parents ca78d68 + 2c8ceb6 commit 459854d
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 1 deletion.
11 changes: 10 additions & 1 deletion immer/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ class array

/*!
* Returns an iterator pointing just after the last element of the
* collection. It does not allocate memory and its complexity is @f$ O(1) @f$.
* collection. It does not allocate memory and its complexity is @f$ O(1)
* @f$.
*/
IMMER_NODISCARD iterator end() const { return impl_.data() + impl_.size; }

Expand Down Expand Up @@ -308,6 +309,14 @@ class array
return transient_type{std::move(impl_)};
}

/*!
* Returns a value that can be used as identity for the container. If two
* values have the same identity, they are guaranteed to be equal and to
* contain the same objects. However, two equal containers are not
* guaranteed to have the same identity.
*/
void* identity() const { return impl_.ptr; }

// Semi-private
const impl_t& impl() const { return impl_; }

Expand Down
11 changes: 11 additions & 0 deletions immer/flex_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,17 @@ class flex_vector
IMMER_NODISCARD transient_type transient() const& { return impl_; }
IMMER_NODISCARD transient_type transient() && { return std::move(impl_); }

/*!
* Returns a value that can be used as identity for the container. If two
* values have the same identity, they are guaranteed to be equal and to
* contain the same objects. However, two equal containers are not
* guaranteed to have the same identity.
*/
std::pair<void*, void*> identity() const
{
return {impl_.root, impl_.tail};
}

// Semi-private
const impl_t& impl() const { return impl_; }

Expand Down
8 changes: 8 additions & 0 deletions immer/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,14 @@ class map
return transient_type{std::move(impl_)};
}

/*!
* Returns a value that can be used as identity for the container. If two
* values have the same identity, they are guaranteed to be equal and to
* contain the same objects. However, two equal containers are not
* guaranteed to have the same identity.
*/
void* identity() const { return impl_.root; }

// Semi-private
const impl_t& impl() const { return impl_; }

Expand Down
8 changes: 8 additions & 0 deletions immer/set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ class set
return transient_type{std::move(impl_)};
}

/*!
* Returns a value that can be used as identity for the container. If two
* values have the same identity, they are guaranteed to be equal and to
* contain the same objects. However, two equal containers are not
* guaranteed to have the same identity.
*/
void* identity() const { return impl_.root; }

// Semi-private
const impl_t& impl() const { return impl_; }

Expand Down
11 changes: 11 additions & 0 deletions immer/vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,17 @@ class vector
IMMER_NODISCARD transient_type transient() const& { return impl_; }
IMMER_NODISCARD transient_type transient() && { return std::move(impl_); }

/*!
* Returns a value that can be used as identity for the container. If two
* values have the same identity, they are guaranteed to be equal and to
* contain the same objects. However, two equal containers are not
* guaranteed to have the same identity.
*/
std::pair<void*, void*> identity() const
{
return {impl_.root, impl_.tail};
}

// Semi-private
const impl_t& impl() const { return impl_; }

Expand Down
6 changes: 6 additions & 0 deletions test/map/generic.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ TEST_CASE("instantiation")
{
auto v = MAP_T<int, int>{};
CHECK(v.size() == 0u);
CHECK(v.identity() == MAP_T<int, int>{}.identity());
}
}

Expand Down Expand Up @@ -173,6 +174,11 @@ TEST_CASE("equals and setting")
CHECK(v.update_if_exists(42, [](auto&& x) { return x + 1; }) ==
v.set(42, 43));

CHECK(v.update_if_exists(1234, [](auto&& x) { return x + 1; }).identity() ==
v.identity());
CHECK(v.update_if_exists(42, [](auto&& x) { return x + 1; }).identity() !=
v.set(42, 43).identity());

#if IMMER_DEBUG_STATS
std::cout << (v.impl().get_debug_stats() + v.impl().get_debug_stats())
.get_summary();
Expand Down
4 changes: 4 additions & 0 deletions test/set/generic.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,16 @@ TEST_CASE("basic insertion")
{
auto v1 = SET_T<unsigned>{};
CHECK(v1.count(42) == 0);
CHECK(v1.identity() == SET_T<unsigned>{}.identity());

auto v2 = v1.insert(42);
CHECK(v1.count(42) == 0);
CHECK(v2.count(42) == 1);
CHECK(v1.identity() != v2.identity());

auto v3 = v2.insert(42);
// it would maybe be nice if this was not the case, but it is...
CHECK(v2.identity() != v3.identity());
CHECK(v1.count(42) == 0);
CHECK(v2.count(42) == 1);
CHECK(v3.count(42) == 1);
Expand Down
6 changes: 6 additions & 0 deletions test/vector/generic.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ TEST_CASE("push back one element")
CHECK(v1.size() == 0u);
CHECK(v2.size() == 1u);
CHECK(v2[0] == 42);

// basic identity rules
auto v3 = v2;
CHECK(v1.identity() != v2.identity());
CHECK(v3.identity() == v2.identity());
CHECK(v1.identity() == VECTOR_T<int>{}.identity());
}

SECTION("many elements")
Expand Down

0 comments on commit 459854d

Please sign in to comment.