Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef BASE_OPTIONAL_H_ | |
| 6 #define BASE_OPTIONAL_H_ | |
| 7 | |
| 8 #include "base/logging.h" | |
| 9 #include "base/memory/aligned_memory.h" | |
| 10 | |
| 11 namespace base { | |
| 12 | |
| 13 // Specification: | |
| 14 // http://en.cppreference.com/w/cpp/experimental/optional/nullopt_t | |
| 15 struct nullopt_t { | |
| 16 explicit nullopt_t(int _) { } | |
|
danakj
2015/11/19 20:55:46
i recently discovered the style guide now says you
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Done.
| |
| 17 }; | |
| 18 | |
| 19 // Specification: | |
| 20 // http://en.cppreference.com/w/cpp/experimental/optional/nullopt | |
| 21 const nullopt_t nullopt(0); | |
| 22 | |
| 23 // base::Optional is a Chromium version of the C++ library experimental optional | |
| 24 // class: http://en.cppreference.com/w/cpp/experimental/optional/optional | |
| 25 // The following methods are not implemented: | |
| 26 // - All methods using rvalue reference (ie. && operator). | |
|
danakj
2015/11/19 20:55:46
I think that I'd like to wait on this until we all
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Kind of. I've updated the list. Let me know how th
| |
| 27 // Thus, instead of operator=(U&&), operator=(const T&) is implemented. | |
| 28 // - Two constructor forms are not implemented. | |
| 29 // - swap() and emplace() are not implemented. | |
| 30 // - Private member |val| is not implemented. | |
| 31 // - Some non-member functions, classes and helper objects are implemented but | |
| 32 // not all. | |
| 33 template <typename T> | |
| 34 class Optional { | |
| 35 public: | |
| 36 Optional() : is_null_(true) { } | |
| 37 Optional(base::nullopt_t opt) : Optional() { } | |
| 38 | |
| 39 Optional(const Optional& other) | |
|
danakj
2015/12/10 23:45:45
Can you add a Optional(Optional&&) constructor?
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
| 40 : Optional() { | |
| 41 if (!other.is_null_) | |
| 42 init(other.value()); | |
| 43 } | |
| 44 | |
| 45 Optional(const T& value) | |
|
danakj
2015/12/10 23:45:46
And an Optional(T&&) constructor
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Done.
| |
| 46 : Optional() { | |
| 47 init(value); | |
| 48 } | |
| 49 | |
| 50 // The difference between the specification and this method is that this | |
| 51 // implementation doesn't use std::is_trivially_destructible. | |
|
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Is it okay to use std::is_trivially_destructible?
| |
| 52 ~Optional() { | |
| 53 free_if_needed(); | |
| 54 } | |
| 55 | |
| 56 Optional& operator=(base::nullopt_t opt) { | |
| 57 free_if_needed(); | |
| 58 return *this; | |
| 59 } | |
| 60 | |
| 61 Optional& operator=(const Optional& other) { | |
|
danakj
2015/12/10 23:45:45
can you add operator=(Optional&&)
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
| 62 if (other.is_null_) { | |
| 63 free_if_needed(); | |
| 64 return *this; | |
| 65 } | |
| 66 | |
| 67 init_or_assign(other.value()); | |
| 68 return *this; | |
| 69 } | |
| 70 | |
| 71 // This method is not part of the current C++ standard. It is instead defined | |
| 72 // as: | |
| 73 // template <class U> | |
| 74 // optional& operator=(U&& value); | |
| 75 Optional& operator=(const T& value) { | |
|
danakj
2015/12/10 23:45:45
Let's make this take a T&&
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done. I've included the per-spec std::enable_if.
| |
| 76 init_or_assign(value); | |
| 77 return *this; | |
| 78 } | |
| 79 | |
| 80 const T* operator->() const { | |
| 81 DCHECK(!is_null_); | |
| 82 return buffer_.template data_as<T>(); | |
| 83 } | |
| 84 | |
| 85 T* operator->() { | |
| 86 DCHECK(!is_null_); | |
| 87 return buffer_.template data_as<T>(); | |
| 88 } | |
| 89 | |
| 90 const T& operator*() const { | |
| 91 return value(); | |
| 92 } | |
| 93 | |
| 94 T& operator*() { | |
| 95 return value(); | |
| 96 } | |
| 97 | |
| 98 explicit operator bool() const { return !is_null_; } | |
|
danakj
2015/12/10 23:45:46
explicit operator is banned: http://chromium-cpp.a
mlamouri (slow - plz ping)
2016/02/29 22:31:26
I couldn't get that to work. The issue is that I c
| |
| 99 | |
| 100 T& value() { | |
|
danakj
2015/12/10 23:45:45
can you ref-quality this with &
mlamouri (slow - plz ping)
2016/02/29 22:31:27
Done.
| |
| 101 DCHECK(!is_null_); | |
| 102 return *buffer_.template data_as<T>(); | |
| 103 } | |
| 104 | |
| 105 const T& value() const { | |
|
danakj
2015/12/10 23:45:45
and this with &,
and add the T&& versions of valu
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
| 106 DCHECK(!is_null_); | |
| 107 return *buffer_.template data_as<T>(); | |
| 108 } | |
| 109 | |
| 110 template <class U> | |
| 111 T value_or(U&& default_value) const { | |
|
danakj
2015/12/10 23:45:46
can add the non-const version of this method too
mlamouri (slow - plz ping)
2016/02/29 22:31:26
Done.
| |
| 112 return is_null_ ? default_value : value(); | |
| 113 } | |
| 114 | |
| 115 bool operator==(const Optional& other) const { | |
| 116 return (is_null_ && other.is_null_) || | |
| 117 (!is_null_ && !other.is_null_ && value() == other.value()); | |
| 118 } | |
| 119 | |
| 120 bool operator!=(const Optional& other) const { | |
| 121 return !this->operator==(other); | |
| 122 } | |
| 123 | |
| 124 private: | |
| 125 void init(const T& value) { | |
| 126 DCHECK(is_null_); | |
| 127 new (buffer_.template data_as<T>()) T(value); | |
| 128 is_null_ = false; | |
| 129 } | |
| 130 | |
| 131 void init_or_assign(const T& value) { | |
| 132 if (is_null_) | |
| 133 init(value); | |
| 134 else | |
| 135 *buffer_.template data_as<T>() = value; | |
| 136 } | |
| 137 | |
| 138 void free_if_needed() { | |
| 139 if (is_null_) | |
| 140 return; | |
| 141 buffer_.template data_as<T>()->~T(); | |
| 142 is_null_ = true; | |
| 143 } | |
| 144 | |
| 145 bool is_null_; | |
| 146 base::AlignedMemory<sizeof(T), ALIGNOF(T)> buffer_; | |
| 147 }; | |
| 148 | |
| 149 } // namespace base | |
| 150 | |
| 151 #endif // BASE_OPTIONAL_H_ | |
| OLD | NEW |