[base] Support base::Optional from std::initializer_list
Chromium allowed std::initializer_list soon after base::Optional was
added to the codebase [1,2], rendering the top level comment incorrect.
This change introduces appropriate overloads for the construcor,
emplace() and make_optional().
[1] https://crrev.com/53f6b258355ce36752ea7a8dcf8953560b5be818
[2] https://crrev.com/0fcb776029fb1380c8e8c9d4cbdcaf7a217ddb5c
Bug: 521269
Change-Id: Iba10136c8ff84d4aa1f77148f8dc238db5c1be4c
Reviewed-on: https://chromium-review.googlesource.com/840008
Commit-Queue: Jan Wilken Dörrie <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Cr-Commit-Position: refs/heads/master@{#526668}
diff --git a/base/optional.h b/base/optional.h
index 00c586726..fbc62893 100644
--- a/base/optional.h
+++ b/base/optional.h
@@ -171,8 +171,6 @@
// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
//
// These are the differences between the specification and the implementation:
-// - The constructor and emplace method using initializer_list are not
-// implemented because 'initializer_list' is banned from Chromium.
// - Constructors do not use 'constexpr' as it is a C++14 extension.
// - 'constexpr' might be missing in some places for reasons specified locally.
// - No exceptions are thrown, because they are banned from Chromium.
@@ -200,6 +198,17 @@
constexpr explicit Optional(in_place_t, Args&&... args)
: internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
+ template <
+ class U,
+ class... Args,
+ class = std::enable_if_t<std::is_constructible<value_type,
+ std::initializer_list<U>&,
+ Args...>::value>>
+ constexpr explicit Optional(in_place_t,
+ std::initializer_list<U> il,
+ Args&&... args)
+ : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
+
~Optional() = default;
// Defer copy-/move- assign operator implementation to OptionalBase.
@@ -314,6 +323,18 @@
Init(std::forward<Args>(args)...);
}
+ template <
+ class U,
+ class... Args,
+ class = std::enable_if_t<std::is_constructible<value_type,
+ std::initializer_list<U>&,
+ Args...>::value>>
+ T& emplace(std::initializer_list<U> il, Args&&... args) {
+ FreeIfNeeded();
+ Init(il, std::forward<Args>(args)...);
+ return storage_.value_;
+ }
+
private:
// Accessing template base class's protected member needs explicit
// declaration to do so.
@@ -506,6 +527,12 @@
return Optional<typename std::decay<T>::type>(std::forward<T>(value));
}
+template <class T, class U, class... Args>
+constexpr Optional<T> make_optional(std::initializer_list<U> il,
+ Args&&... args) {
+ return Optional<T>(in_place, il, std::forward<Args>(args)...);
+}
+
template <class T>
void swap(Optional<T>& lhs, Optional<T>& rhs) {
lhs.swap(rhs);