[stdcompat]: Update utility.
utility polyfill providing in_place_t* tags and added test into
utility_test.cc. The test is simply checking that when we are
not using our polyfills (and version appropiate) we default to using the
std::* version of the tags.
Bug: 57349
Test: stdcompat-test
Change-Id: Ida71246d8583ed8c589ba031a783be2608f99311
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/466480
Commit-Queue: Gianfranco Valentino <gevalentino@google.com>
Reviewed-by: Roland McGrath <mcgrathr@google.com>
diff --git a/zircon/system/ulib/stdcompat/BUILD.gn b/zircon/system/ulib/stdcompat/BUILD.gn
index 2e43543..f95361f 100644
--- a/zircon/system/ulib/stdcompat/BUILD.gn
+++ b/zircon/system/ulib/stdcompat/BUILD.gn
@@ -18,6 +18,7 @@
sdk_headers = [
"lib/stdcompat/version.h",
"lib/stdcompat/type_traits.h",
+ "lib/stdcompat/utility.h",
]
sources = [
"include/lib/stdcompat/internal/constructors.h",
diff --git a/zircon/system/ulib/stdcompat/BUILD.zircon.gn b/zircon/system/ulib/stdcompat/BUILD.zircon.gn
index e80e5af..3caf68d 100644
--- a/zircon/system/ulib/stdcompat/BUILD.zircon.gn
+++ b/zircon/system/ulib/stdcompat/BUILD.zircon.gn
@@ -18,6 +18,7 @@
sdk_headers = [
"lib/stdcompat/version.h",
"lib/stdcompat/type_traits.h",
+ "lib/stdcompat/utility.h",
]
sources = [
"include/lib/stdcompat/internal/constructors.h",
diff --git a/zircon/system/ulib/stdcompat/include/lib/stdcompat/internal/utility.h b/zircon/system/ulib/stdcompat/include/lib/stdcompat/internal/utility.h
index a000609..f029508 100644
--- a/zircon/system/ulib/stdcompat/include/lib/stdcompat/internal/utility.h
+++ b/zircon/system/ulib/stdcompat/include/lib/stdcompat/internal/utility.h
@@ -5,7 +5,6 @@
#ifndef LIB_STDCOMPAT_INTERNAL_UTILITY_H_
#define LIB_STDCOMPAT_INTERNAL_UTILITY_H_
-#include <type_traits>
#include <utility>
#include "../type_traits.h"
@@ -13,6 +12,11 @@
namespace cpp17 {
namespace internal {
+template <typename Tag>
+struct instantiate_templated_tag {
+ static constexpr Tag storage;
+};
+
// Utility to return the first type in a parameter pack.
template <typename... Ts>
struct first;
diff --git a/zircon/system/ulib/stdcompat/include/lib/stdcompat/utility.h b/zircon/system/ulib/stdcompat/include/lib/stdcompat/utility.h
index e08a72d..5f77a5db 100644
--- a/zircon/system/ulib/stdcompat/include/lib/stdcompat/utility.h
+++ b/zircon/system/ulib/stdcompat/include/lib/stdcompat/utility.h
@@ -2,12 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef LIB_STDCOMPAT_INTERNAL_IN_PLACE_INTERNAL_H_
-#define LIB_STDCOMPAT_INTERNAL_IN_PLACE_INTERNAL_H_
+#ifndef LIB_STDCOMPAT_UTILITY_H_
+#define LIB_STDCOMPAT_UTILITY_H_
-#include <cstddef>
+#include <lib/stdcompat/internal/utility.h>
-namespace fit {
+#include <utility>
+
+namespace cpp17 {
+// Use alias for cpp17 and above.
+#if __cplusplus >= 201411L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+
+using std::in_place;
+using std::in_place_t;
+
+using std::in_place_index;
+using std::in_place_index_t;
+
+using std::in_place_type;
+using std::in_place_type_t;
+
+#else // Provide provide polyfills for |in_place*| types and variables.
// Tag for requesting in-place initialization.
struct in_place_t {
@@ -26,58 +41,34 @@
explicit constexpr in_place_index_t() = default;
};
-#ifdef __cpp_inline_variables
+// Use inline variables if available.
+#if __cpp_inline_variables >= 201606L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
-// Inline variables are only available on C++ 17 and beyond.
-
-inline constexpr in_place_t in_place{};
+constexpr in_place_t in_place{};
template <typename T>
-inline constexpr in_place_type_t<T> in_place_type{};
+constexpr in_place_type_t<T> in_place_type{};
template <size_t Index>
-inline constexpr in_place_index_t<Index> in_place_index{};
+constexpr in_place_index_t<Index> in_place_index{};
-#else
+#else // Provide polyfill reference to provided variable storage.
-// For C++ 14 we need to provide storage for the variable so we define
-// a reference instead.
-
-template <typename Placeholder = void>
-struct in_place_holder {
- static constexpr in_place_t instance{};
-};
+static constexpr const in_place_t& in_place =
+ internal::instantiate_templated_tag<in_place_t>::storage;
template <typename T>
-struct in_place_type_holder {
- static constexpr in_place_type_t<T> instance{};
-};
-
-template <size_t Index>
-struct in_place_index_holder {
- static constexpr in_place_index_t<Index> instance{};
-};
-
-template <typename Placeholder>
-constexpr in_place_t in_place_holder<Placeholder>::instance;
-
-template <typename T>
-constexpr in_place_type_t<T> in_place_type_holder<T>::instance;
-
-template <size_t Index>
-constexpr in_place_index_t<Index> in_place_index_holder<Index>::instance;
-
-static constexpr const in_place_t& in_place = in_place_holder<>::instance;
-
-template <typename T>
-static constexpr const in_place_type_t<T>& in_place_type = in_place_type_holder<T>::instance;
+static constexpr const in_place_type_t<T>& in_place_type =
+ internal::instantiate_templated_tag<in_place_type_t<T>>::storage;
template <size_t Index>
static constexpr const in_place_index_t<Index>& in_place_index =
- in_place_index_holder<Index>::instance;
+ internal::instantiate_templated_tag<in_place_index_t<Index>>::storage;
-#endif // __cpp_inline_variables
+#endif // __cpp_inline_variables >= 201606L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
-} // namespace fit
+#endif // __cplusplus >= 201411L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
-#endif // LIB_STDCOMPAT_INTERNAL_IN_PLACE_INTERNAL_H_
+} // namespace cpp17
+
+#endif // LIB_STDCOMPAT_UTILITY_H_
diff --git a/zircon/system/ulib/stdcompat/test/BUILD.gn b/zircon/system/ulib/stdcompat/test/BUILD.gn
index 28e5d28..9e1d941 100644
--- a/zircon/system/ulib/stdcompat/test/BUILD.gn
+++ b/zircon/system/ulib/stdcompat/test/BUILD.gn
@@ -19,6 +19,7 @@
"constructors_internal_test.cc",
"traits_test.cc",
"utility_internal_test.cc",
+ "utility_test.cc",
"version_test.cc",
]
diff --git a/zircon/system/ulib/stdcompat/test/utility_internal_test.cc b/zircon/system/ulib/stdcompat/test/utility_internal_test.cc
index a647403..3daa3ba 100644
--- a/zircon/system/ulib/stdcompat/test/utility_internal_test.cc
+++ b/zircon/system/ulib/stdcompat/test/utility_internal_test.cc
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <lib/stdcompat/internal/utility.h>
-
-#include <type_traits>
+#include <lib/stdcompat/type_traits.h>
+#include <lib/stdcompat/utility.h>
#include <gtest/gtest.h>
@@ -12,9 +11,9 @@
TEST(InternalTypeTraitsTest, FirstTReturnsFirstTypeInParameterPack) {
using cpp17::internal::first_t;
- static_assert(std::is_same_v<int, first_t<int>>, "");
- static_assert(std::is_same_v<int, first_t<int, char>>, "");
- static_assert(std::is_same_v<int, first_t<int, char, bool>>, "");
+ static_assert(std::is_same<int, first_t<int>>::value, "");
+ static_assert(std::is_same<int, first_t<int, char>>::value, "");
+ static_assert(std::is_same<int, first_t<int, char, bool>>::value, "");
}
TEST(InternalTypeTraitsTest, OccurrencesOfReturnsNumberOfTimesTypeIsPresent) {
@@ -164,4 +163,4 @@
static_assert(!is_comparable(comparable_c{}, comparable_c{}), "");
}
-} // anonymous namespace
+} // namespace
diff --git a/zircon/system/ulib/stdcompat/test/utility_test.cc b/zircon/system/ulib/stdcompat/test/utility_test.cc
new file mode 100644
index 0000000..72ce89e
--- /dev/null
+++ b/zircon/system/ulib/stdcompat/test/utility_test.cc
@@ -0,0 +1,36 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <lib/stdcompat/utility.h>
+
+#include <gtest/gtest.h>
+
+namespace {
+
+TEST(InplaceTagTest, InplaceTagsSwitchToStdProvidedOnStd17) {
+ static_assert(std::is_trivially_default_constructible<cpp17::in_place_t>::value);
+ static_assert(std::is_trivially_default_constructible<cpp17::in_place_index_t<0>>::value);
+ static_assert(std::is_trivially_default_constructible<cpp17::in_place_type_t<void>>::value);
+
+#if __cplusplus >= 201411L && !defined(LIB_STDCOMPAT_USE_POLYFILLS)
+ static_assert(std::is_same<cpp17::in_place_t, std::in_place_t>::value);
+ static_assert(std::is_same<cpp17::in_place_type_t<void>, std::in_place_type_t<void>>::value);
+ static_assert(std::is_same<cpp17::in_place_index_t<0>, std::in_place_index_t<0>>::value);
+
+ static_assert(std::addressof(cpp17::in_place) == std::addressof(std::in_place));
+ static_assert(std::addressof(cpp17::in_place_type<void>) ==
+ std::addressof(std::in_place_type<void>));
+ static_assert(std::addressof(cpp17::in_place_index<0>) == std::addressof(std::in_place_index<0>));
+#else // Force template instantiation.
+
+ // Sanity checks that the instantiations are actually different for the polyfills.
+ static_assert(std::addressof(cpp17::in_place) != nullptr);
+ static_assert(static_cast<const void*>(std::addressof(cpp17::in_place_type<void>)) !=
+ static_cast<const void*>(std::addressof(std::in_place_type<int>)));
+ static_assert(static_cast<const void*>(std::addressof(cpp17::in_place_index<0>)) !=
+ static_cast<const void*>(std::addressof(std::in_place_index<1>)));
+#endif
+}
+
+} // namespace