Commit 594f4d72 authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook Github Bot

Round-trip iteration order for F14Vector{Map,Set}

Summary: `F14Vector{Map,Set}` have specified iteration order: inverse insertion order. When serialized, however, the order does not round-trip (in fact, it flips). This diff introduces an extension point to specify the iteration order for serialization, and it specializes it for F14 to make the iteration order round-trip.

Reviewed By: vitaut

Differential Revision: D17108774

fbshipit-source-id: 466b746baacff861242729bfa62447c138094cee
parent 55e5070f
......@@ -810,3 +810,23 @@ template <>
struct is_unsigned<unsigned __int128> : ::std::true_type {};
FOLLY_NAMESPACE_STD_END
#endif // FOLLY_SUPPLY_MISSING_INT128_TRAITS
namespace folly {
/**
* Extension point for containers to provide an order such that if entries are
* inserted into a new instance in that order, iteration order of the new
* instance matches the original's. This can be useful for containers that have
* defined but non-FIFO iteration order, such as F14Vector*.
*
* Should return an iterable view (a type that provides begin() and end()).
*
* Containers should provide overloads in their own namespace; resolution is
* expected to be done via ADL.
*/
template <typename Container>
const Container& order_preserving_reinsertion_view(const Container& container) {
return container;
}
} // namespace folly
......@@ -29,6 +29,7 @@
#include <stdexcept>
#include <folly/Range.h>
#include <folly/Traits.h>
#include <folly/lang/Exception.h>
#include <folly/lang/SafeAssert.h>
......@@ -1139,6 +1140,12 @@ class F14VectorMap : public f14::detail::F14VectorMapImpl<
}
};
template <typename K, typename M, typename H, typename E, typename A>
Range<typename F14VectorMap<K, M, H, E, A>::const_reverse_iterator>
order_preserving_reinsertion_view(const F14VectorMap<K, M, H, E, A>& c) {
return {c.rbegin(), c.rend()};
}
template <
typename Key,
typename Mapped,
......
......@@ -975,6 +975,12 @@ class F14VectorSet
}
};
template <typename K, typename H, typename E, typename A>
Range<typename F14VectorSet<K, H, E, A>::const_reverse_iterator>
order_preserving_reinsertion_view(const F14VectorSet<K, H, E, A>& c) {
return {c.rbegin(), c.rend()};
}
template <typename Key, typename Hasher, typename KeyEqual, typename Alloc>
class F14FastSet
: public std::conditional_t<
......
......@@ -842,6 +842,20 @@ TEST(F14VectorMap, reverse_iterator) {
}
}
TEST(F14VectorMap, OrderPreservingReinsertionView) {
F14VectorMap<int, int> m1;
for (size_t i = 0; i < 5; ++i) {
m1.emplace(i, i);
}
F14VectorMap<int, int> m2;
for (const auto& kv : order_preserving_reinsertion_view(m1)) {
m2.insert(kv);
}
EXPECT_EQ(asVector(m1), asVector(m2));
}
TEST(F14ValueMap, eraseWhileIterating) {
runEraseWhileIterating<F14ValueMap<int, int>>();
}
......
......@@ -764,6 +764,20 @@ TEST(F14VectorMap, reverse_iterator) {
}
}
TEST(F14VectorSet, OrderPreservingReinsertionView) {
F14VectorSet<int> s1;
for (size_t i = 0; i < 5; ++i) {
s1.emplace(i);
}
F14VectorSet<int> s2;
for (const auto& k : order_preserving_reinsertion_view(s1)) {
s2.insert(k);
}
EXPECT_EQ(asVector(s1), asVector(s2));
}
TEST(F14ValueSet, eraseWhileIterating) {
runEraseWhileIterating<F14ValueSet<int>>();
}
......
......@@ -18,6 +18,7 @@
#include <cstddef>
#include <ostream>
#include <type_traits>
#include <vector>
#include <folly/container/detail/F14Policy.h>
......@@ -106,5 +107,11 @@ inline std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) {
return xo;
}
template <typename Container>
std::vector<typename std::decay_t<Container>::value_type> asVector(
const Container& c) {
return {c.begin(), c.end()};
}
} // namespace f14
} // namespace folly
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment