Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: base/optional.h

Issue 2434253003: Make base::Optional constructor constexpr. (Closed)
Patch Set: Remove delegating ctor from nullopt ctor Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/optional_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_OPTIONAL_H_ 5 #ifndef BASE_OPTIONAL_H_
6 #define BASE_OPTIONAL_H_ 6 #define BASE_OPTIONAL_H_
7 7
8 #include <type_traits> 8 #include <type_traits>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 16 matching lines...) Expand all
27 constexpr in_place_t in_place = {}; 27 constexpr in_place_t in_place = {};
28 28
29 // Specification: 29 // Specification:
30 // http://en.cppreference.com/w/cpp/utility/optional/nullopt 30 // http://en.cppreference.com/w/cpp/utility/optional/nullopt
31 constexpr nullopt_t nullopt(0); 31 constexpr nullopt_t nullopt(0);
32 32
33 namespace internal { 33 namespace internal {
34 34
35 template <typename T, bool = base::is_trivially_destructible<T>::value> 35 template <typename T, bool = base::is_trivially_destructible<T>::value>
36 struct OptionalStorage { 36 struct OptionalStorage {
37 OptionalStorage() {} 37 constexpr OptionalStorage() {}
38
39 constexpr explicit OptionalStorage(const T& value)
40 : is_null_(false), value_(value) {}
41
42 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14.
43 explicit OptionalStorage(T&& value)
44 : is_null_(false), value_(std::move(value)) {}
45
46 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14.
47 template <class... Args>
48 explicit OptionalStorage(base::in_place_t, Args&&... args)
49 : is_null_(false), value_(std::forward<Args>(args)...) {}
50
38 // When T is not trivially destructible we must call its 51 // When T is not trivially destructible we must call its
39 // destructor before deallocating its memory. 52 // destructor before deallocating its memory.
40 ~OptionalStorage() { 53 ~OptionalStorage() {
41 if (!is_null_) 54 if (!is_null_)
42 value_.~T(); 55 value_.~T();
43 } 56 }
44 57
45 bool is_null_ = true; 58 bool is_null_ = true;
46 union { 59 union {
47 // |empty_| exists so that the union will always be initialized, even when 60 // |empty_| exists so that the union will always be initialized, even when
48 // it doesn't contain a value. Not initializing it has been observed to 61 // it doesn't contain a value. Not initializing it has been observed to
49 // trigger comiler warnings. 62 // trigger comiler warnings.
50 char empty_ = '\0'; 63 char empty_ = '\0';
51 T value_; 64 T value_;
52 }; 65 };
53 }; 66 };
54 67
55 template <typename T> 68 template <typename T>
56 struct OptionalStorage<T, true> { 69 struct OptionalStorage<T, true> {
57 OptionalStorage() {} 70 constexpr OptionalStorage() {}
71
72 constexpr explicit OptionalStorage(const T& value)
73 : is_null_(false), value_(value) {}
74
75 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14.
76 explicit OptionalStorage(T&& value)
77 : is_null_(false), value_(std::move(value)) {}
78
79 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14.
80 template <class... Args>
81 explicit OptionalStorage(base::in_place_t, Args&&... args)
82 : is_null_(false), value_(std::forward<Args>(args)...) {}
83
58 // When T is trivially destructible (i.e. its destructor does nothing) there 84 // When T is trivially destructible (i.e. its destructor does nothing) there
59 // is no need to call it. Explicitly defaulting the destructor means it's not 85 // is no need to call it. Explicitly defaulting the destructor means it's not
60 // user-provided. Those two together make this destructor trivial. 86 // user-provided. Those two together make this destructor trivial.
61 ~OptionalStorage() = default; 87 ~OptionalStorage() = default;
62 88
63 bool is_null_ = true; 89 bool is_null_ = true;
64 union { 90 union {
65 // |empty_| exists so that the union will always be initialized, even when 91 // |empty_| exists so that the union will always be initialized, even when
66 // it doesn't contain a value. Not initializing it has been observed to 92 // it doesn't contain a value. Not initializing it has been observed to
67 // trigger comiler warnings. 93 // trigger comiler warnings.
(...skipping 16 matching lines...) Expand all
84 // - Constructors do not use 'constexpr' as it is a C++14 extension. 110 // - Constructors do not use 'constexpr' as it is a C++14 extension.
85 // - 'constexpr' might be missing in some places for reasons specified locally. 111 // - 'constexpr' might be missing in some places for reasons specified locally.
86 // - No exceptions are thrown, because they are banned from Chromium. 112 // - No exceptions are thrown, because they are banned from Chromium.
87 // - All the non-members are in the 'base' namespace instead of 'std'. 113 // - All the non-members are in the 'base' namespace instead of 'std'.
88 template <typename T> 114 template <typename T>
89 class Optional { 115 class Optional {
90 public: 116 public:
91 using value_type = T; 117 using value_type = T;
92 118
93 constexpr Optional() = default; 119 constexpr Optional() = default;
94 Optional(base::nullopt_t) : Optional() {} 120
121 constexpr Optional(base::nullopt_t) {}
95 122
96 Optional(const Optional& other) { 123 Optional(const Optional& other) {
97 if (!other.storage_.is_null_) 124 if (!other.storage_.is_null_)
98 Init(other.value()); 125 Init(other.value());
99 } 126 }
100 127
101 Optional(Optional&& other) { 128 Optional(Optional&& other) {
102 if (!other.storage_.is_null_) 129 if (!other.storage_.is_null_)
103 Init(std::move(other.value())); 130 Init(std::move(other.value()));
104 } 131 }
105 132
106 Optional(const T& value) { Init(value); } 133 constexpr Optional(const T& value) : storage_(value) {}
107 134
108 Optional(T&& value) { Init(std::move(value)); } 135 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14.
136 Optional(T&& value) : storage_(std::move(value)) {}
109 137
138 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14.
110 template <class... Args> 139 template <class... Args>
111 explicit Optional(base::in_place_t, Args&&... args) { 140 explicit Optional(base::in_place_t, Args&&... args)
112 emplace(std::forward<Args>(args)...); 141 : storage_(base::in_place, std::forward<Args>(args)...) {}
113 }
114 142
115 ~Optional() = default; 143 ~Optional() = default;
116 144
117 Optional& operator=(base::nullopt_t) { 145 Optional& operator=(base::nullopt_t) {
118 FreeIfNeeded(); 146 FreeIfNeeded();
119 return *this; 147 return *this;
120 } 148 }
121 149
122 Optional& operator=(const Optional& other) { 150 Optional& operator=(const Optional& other) {
123 if (other.storage_.is_null_) { 151 if (other.storage_.is_null_) {
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 template <class T> 493 template <class T>
466 struct hash<base::Optional<T>> { 494 struct hash<base::Optional<T>> {
467 size_t operator()(const base::Optional<T>& opt) const { 495 size_t operator()(const base::Optional<T>& opt) const {
468 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); 496 return opt == base::nullopt ? 0 : std::hash<T>()(*opt);
469 } 497 }
470 }; 498 };
471 499
472 } // namespace std 500 } // namespace std
473 501
474 #endif // BASE_OPTIONAL_H_ 502 #endif // BASE_OPTIONAL_H_
OLDNEW
« no previous file with comments | « no previous file | base/optional_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698