Chromium Code Reviews| Index: base/optional.h |
| diff --git a/base/optional.h b/base/optional.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c0b2a0c61c90f5a59c9dc541211dee3fb15e5cc2 |
| --- /dev/null |
| +++ b/base/optional.h |
| @@ -0,0 +1,151 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef BASE_OPTIONAL_H_ |
| +#define BASE_OPTIONAL_H_ |
| + |
| +#include "base/logging.h" |
| +#include "base/memory/aligned_memory.h" |
| + |
| +namespace base { |
| + |
| +// Specification: |
| +// http://en.cppreference.com/w/cpp/experimental/optional/nullopt_t |
| +struct nullopt_t { |
| + 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.
|
| +}; |
| + |
| +// Specification: |
| +// http://en.cppreference.com/w/cpp/experimental/optional/nullopt |
| +const nullopt_t nullopt(0); |
| + |
| +// base::Optional is a Chromium version of the C++ library experimental optional |
| +// class: http://en.cppreference.com/w/cpp/experimental/optional/optional |
| +// The following methods are not implemented: |
| +// - 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
|
| +// Thus, instead of operator=(U&&), operator=(const T&) is implemented. |
| +// - Two constructor forms are not implemented. |
| +// - swap() and emplace() are not implemented. |
| +// - Private member |val| is not implemented. |
| +// - Some non-member functions, classes and helper objects are implemented but |
| +// not all. |
| +template <typename T> |
| +class Optional { |
| + public: |
| + Optional() : is_null_(true) { } |
| + Optional(base::nullopt_t opt) : Optional() { } |
| + |
| + 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.
|
| + : Optional() { |
| + if (!other.is_null_) |
| + init(other.value()); |
| + } |
| + |
| + 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.
|
| + : Optional() { |
| + init(value); |
| + } |
| + |
| + // The difference between the specification and this method is that this |
| + // 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?
|
| + ~Optional() { |
| + free_if_needed(); |
| + } |
| + |
| + Optional& operator=(base::nullopt_t opt) { |
| + free_if_needed(); |
| + return *this; |
| + } |
| + |
| + 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.
|
| + if (other.is_null_) { |
| + free_if_needed(); |
| + return *this; |
| + } |
| + |
| + init_or_assign(other.value()); |
| + return *this; |
| + } |
| + |
| + // This method is not part of the current C++ standard. It is instead defined |
| + // as: |
| + // template <class U> |
| + // optional& operator=(U&& value); |
| + 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.
|
| + init_or_assign(value); |
| + return *this; |
| + } |
| + |
| + const T* operator->() const { |
| + DCHECK(!is_null_); |
| + return buffer_.template data_as<T>(); |
| + } |
| + |
| + T* operator->() { |
| + DCHECK(!is_null_); |
| + return buffer_.template data_as<T>(); |
| + } |
| + |
| + const T& operator*() const { |
| + return value(); |
| + } |
| + |
| + T& operator*() { |
| + return value(); |
| + } |
| + |
| + 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
|
| + |
| + 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.
|
| + DCHECK(!is_null_); |
| + return *buffer_.template data_as<T>(); |
| + } |
| + |
| + 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.
|
| + DCHECK(!is_null_); |
| + return *buffer_.template data_as<T>(); |
| + } |
| + |
| + template <class U> |
| + 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.
|
| + return is_null_ ? default_value : value(); |
| + } |
| + |
| + bool operator==(const Optional& other) const { |
| + return (is_null_ && other.is_null_) || |
| + (!is_null_ && !other.is_null_ && value() == other.value()); |
| + } |
| + |
| + bool operator!=(const Optional& other) const { |
| + return !this->operator==(other); |
| + } |
| + |
| + private: |
| + void init(const T& value) { |
| + DCHECK(is_null_); |
| + new (buffer_.template data_as<T>()) T(value); |
| + is_null_ = false; |
| + } |
| + |
| + void init_or_assign(const T& value) { |
| + if (is_null_) |
| + init(value); |
| + else |
| + *buffer_.template data_as<T>() = value; |
| + } |
| + |
| + void free_if_needed() { |
| + if (is_null_) |
| + return; |
| + buffer_.template data_as<T>()->~T(); |
| + is_null_ = true; |
| + } |
| + |
| + bool is_null_; |
| + base::AlignedMemory<sizeof(T), ALIGNOF(T)> buffer_; |
| +}; |
| + |
| +} // namespace base |
| + |
| +#endif // BASE_OPTIONAL_H_ |