FTL: Add SmallMap<K, V, N>
SmallMap is a SmallVector of unordered key-value pairs. This CL includes
construction and lookup, while mutators will be added in a follow-up CL.
Bug: 160012986
Test: ftl_test
Change-Id: Id88485304c7d7f515226b4f8edf63ce9af6a2157
diff --git a/include/ftl/InitializerList.h b/include/ftl/InitializerList.h
index 204f79b..bb99280 100644
--- a/include/ftl/InitializerList.h
+++ b/include/ftl/InitializerList.h
@@ -34,6 +34,14 @@
//
// ... = ftl::init::list<std::string>("abc")()(3u, '?');
//
+// The following syntax is a shorthand for key-value pairs, where the first argument is the
+// key, and the rest construct the value. The types of the key and value are deduced if the
+// first pair contains exactly two arguments:
+//
+// ... = ftl::init::map<int, std::string>(-1, "abc")(-2)(-3, 3u, '?');
+//
+// ... = ftl::init::map(0, 'a')(1, 'b')(2, 'c');
+//
// WARNING: The InitializerList returned by an ftl::init::list expression must be consumed
// immediately, since temporary arguments are destroyed after the full expression. Storing
// an InitializerList results in dangling references.
@@ -58,6 +66,29 @@
std::tuple<Types...> tuple;
};
+template <typename K, typename V>
+struct KeyValue {};
+
+// Shorthand for key-value pairs that assigns the first argument to the key, and the rest to the
+// value. The specialization is on KeyValue rather than std::pair, so that ftl::init::list works
+// with the latter.
+template <typename K, typename V, size_t... Sizes, typename... Types>
+struct InitializerList<KeyValue<K, V>, std::index_sequence<Sizes...>, Types...> {
+ // Accumulate the three arguments to std::pair's piecewise constructor.
+ template <typename... Args>
+ [[nodiscard]] constexpr auto operator()(K&& k, Args&&... args) && -> InitializerList<
+ KeyValue<K, V>, std::index_sequence<Sizes..., 3>, Types..., std::piecewise_construct_t,
+ std::tuple<K&&>, std::tuple<Args&&...>> {
+ return {std::tuple_cat(std::move(tuple),
+ std::forward_as_tuple(std::piecewise_construct,
+ std::forward_as_tuple(std::forward<K>(k)),
+ std::forward_as_tuple(
+ std::forward<Args>(args)...)))};
+ }
+
+ std::tuple<Types...> tuple;
+};
+
namespace init {
template <typename T, typename... Args>
@@ -65,5 +96,15 @@
return InitializerList<T>{}(std::forward<Args>(args)...);
}
+template <typename K, typename V, typename... Args>
+[[nodiscard]] constexpr auto map(Args&&... args) {
+ return list<KeyValue<K, V>>(std::forward<Args>(args)...);
+}
+
+template <typename K, typename V>
+[[nodiscard]] constexpr auto map(K&& k, V&& v) {
+ return list<KeyValue<K, V>>(std::forward<K>(k), std::forward<V>(v));
+}
+
} // namespace init
} // namespace android::ftl