pw_minimal_cpp_stdlib: Various additions

- Implement a few library features: std::equal and
  std::lexicographical_compare, std::launder, std::add_rvalue_reference,
  std::add_lvalue_reference, std::negation.
- Conditionally include <vector> on key_value_store_test.cc.

Change-Id: I9efb16c385b4ff2005cfd737da1efe9d95fe1bdd
diff --git a/pw_kvs/key_value_store_test.cc b/pw_kvs/key_value_store_test.cc
index c54d6e7..401ef8e 100644
--- a/pw_kvs/key_value_store_test.cc
+++ b/pw_kvs/key_value_store_test.cc
@@ -21,7 +21,10 @@
 #include <array>
 #include <cstdio>
 #include <cstring>
+
+#if DUMP_KVS_STATE_TO_FILE
 #include <vector>
+#endif  // DUMP_KVS_STATE_TO_FILE
 
 #include "gtest/gtest.h"
 #include "pw_checksum/ccitt_crc16.h"
diff --git a/pw_minimal_cpp_stdlib/public/internal/algorithm.h b/pw_minimal_cpp_stdlib/public/internal/algorithm.h
index 2556702..f905e11 100644
--- a/pw_minimal_cpp_stdlib/public/internal/algorithm.h
+++ b/pw_minimal_cpp_stdlib/public/internal/algorithm.h
@@ -37,4 +37,38 @@
   return static_cast<T&&>(value);
 }
 
+template <class LhsIterator, class RhsIterator>
+constexpr bool equal(LhsIterator first_l,
+                     LhsIterator last_l,
+                     RhsIterator first_r,
+                     RhsIterator last_r) {
+  while (first_l != last_l && first_r != last_r) {
+    if (*first_l != *first_r) {
+      return false;
+    }
+    ++first_l;
+    ++first_r;
+  }
+  return first_l == last_l && first_r == last_r;
+}
+
+template <class LhsIterator, class RhsIterator>
+constexpr bool lexicographical_compare(LhsIterator first_l,
+                                       LhsIterator last_l,
+                                       RhsIterator first_r,
+                                       RhsIterator last_r) {
+  while (first_l != last_l && first_r != last_r) {
+    if (*first_l < *first_r) {
+      return true;
+    }
+    if (*first_r < *first_l) {
+      return false;
+    }
+
+    ++first_l;
+    ++first_r;
+  }
+  return (first_l == last_l) && (first_r != last_r);
+}
+
 }  // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/iterator.h b/pw_minimal_cpp_stdlib/public/internal/iterator.h
index 9c5e9ad..4470731 100644
--- a/pw_minimal_cpp_stdlib/public/internal/iterator.h
+++ b/pw_minimal_cpp_stdlib/public/internal/iterator.h
@@ -44,6 +44,10 @@
   return kSize;
 }
 
+// NOT IMPLEMENTED: iterator_traits does not work
+template <typename>
+struct iterator_traits {};
+
 // NOT IMPLEMENTED: Reverse iterators are not implemented.
 template <typename>
 struct reverse_iterator;
diff --git a/pw_minimal_cpp_stdlib/public/internal/new.h b/pw_minimal_cpp_stdlib/public/internal/new.h
index d21d991..b7a583c 100644
--- a/pw_minimal_cpp_stdlib/public/internal/new.h
+++ b/pw_minimal_cpp_stdlib/public/internal/new.h
@@ -15,3 +15,14 @@
 
 // Placement new
 inline void* operator new(decltype(sizeof(0)), void* ptr) { return ptr; }
+
+#define __cpp_lib_launder 201606L
+
+namespace std {
+
+template <typename T>
+[[nodiscard]] constexpr T* launder(T* pointer) noexcept {
+  return __builtin_launder(pointer);
+}
+
+}  // namespace std
diff --git a/pw_minimal_cpp_stdlib/public/internal/type_traits.h b/pw_minimal_cpp_stdlib/public/internal/type_traits.h
index 422b2df..366f568 100644
--- a/pw_minimal_cpp_stdlib/public/internal/type_traits.h
+++ b/pw_minimal_cpp_stdlib/public/internal/type_traits.h
@@ -206,6 +206,12 @@
 template <typename T>
 inline constexpr bool is_void_v = is_void<T>::value;
 
+template <typename T>
+struct negation : bool_constant<!bool(T::value)> {};
+
+template <typename T>
+inline constexpr bool negation_v = negation<T>::value;
+
 template <bool kBool, typename TrueType, typename FalseType>
 struct conditional {
   using type = TrueType;
@@ -358,11 +364,30 @@
 template <typename...>
 using void_t = void;
 
-// NOT IMPLEMENTED: add_rvalue_refernce does work with reference types.
+namespace impl {
+
 template <typename T>
-struct add_rvalue_reference {
-  using type = T&&;
-};
+type_identity<T&> AddLValueReference(int);
+
+template <typename T>
+type_identity<T> AddLValueReference(...);
+
+template <typename T>
+type_identity<T&&> AddRValueReference(int);
+
+template <typename T>
+type_identity<T> AddRValueReference(...);
+
+}  // namespace impl
+
+template <class T>
+struct add_lvalue_reference : decltype(impl::AddLValueReference<T>(0)) {};
+
+template <typename T>
+using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
+
+template <class T>
+struct add_rvalue_reference : decltype(impl::AddRValueReference<T>(0)) {};
 
 template <typename T>
 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
diff --git a/pw_minimal_cpp_stdlib/test.cc b/pw_minimal_cpp_stdlib/test.cc
index 3b1d42a..a29f649 100644
--- a/pw_minimal_cpp_stdlib/test.cc
+++ b/pw_minimal_cpp_stdlib/test.cc
@@ -134,7 +134,7 @@
                 18446744073709551615ull);
 }
 
-TEST(New, Basic) {
+TEST(New, PlacementNew) {
   unsigned char value[4];
   new (value) int(1234);
 
@@ -143,6 +143,12 @@
   EXPECT_EQ(1234, int_value);
 }
 
+TEST(New, Launder) {
+  unsigned char value[4];
+  int* int_ptr = std::launder(reinterpret_cast<int*>(value));
+  EXPECT_EQ(static_cast<void*>(int_ptr), static_cast<void*>(value));
+}
+
 TEST(StringView, Basic) {
   constexpr std::string_view value("1234567890");
   static_assert(value.size() == 10);