[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);