OLD | NEW |
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 Loading... |
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 constexpr OptionalStorage() {} | 37 // Initializing |empty_| here instead of using default member initializing |
| 38 // to avoid errors in g++ 4.8. |
| 39 constexpr OptionalStorage() : empty_('\0') {} |
38 | 40 |
39 constexpr explicit OptionalStorage(const T& value) | 41 constexpr explicit OptionalStorage(const T& value) |
40 : is_null_(false), value_(value) {} | 42 : is_null_(false), value_(value) {} |
41 | 43 |
42 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. | 44 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. |
43 explicit OptionalStorage(T&& value) | 45 explicit OptionalStorage(T&& value) |
44 : is_null_(false), value_(std::move(value)) {} | 46 : is_null_(false), value_(std::move(value)) {} |
45 | 47 |
46 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. | 48 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. |
47 template <class... Args> | 49 template <class... Args> |
48 explicit OptionalStorage(base::in_place_t, Args&&... args) | 50 explicit OptionalStorage(base::in_place_t, Args&&... args) |
49 : is_null_(false), value_(std::forward<Args>(args)...) {} | 51 : is_null_(false), value_(std::forward<Args>(args)...) {} |
50 | 52 |
51 // When T is not trivially destructible we must call its | 53 // When T is not trivially destructible we must call its |
52 // destructor before deallocating its memory. | 54 // destructor before deallocating its memory. |
53 ~OptionalStorage() { | 55 ~OptionalStorage() { |
54 if (!is_null_) | 56 if (!is_null_) |
55 value_.~T(); | 57 value_.~T(); |
56 } | 58 } |
57 | 59 |
58 bool is_null_ = true; | 60 bool is_null_ = true; |
59 union { | 61 union { |
60 // |empty_| exists so that the union will always be initialized, even when | 62 // |empty_| exists so that the union will always be initialized, even when |
61 // it doesn't contain a value. Not initializing it has been observed to | 63 // it doesn't contain a value. Union members must be initialized for the |
62 // trigger comiler warnings. | 64 // constructor to be 'constexpr'. |
63 char empty_ = '\0'; | 65 char empty_; |
64 T value_; | 66 T value_; |
65 }; | 67 }; |
66 }; | 68 }; |
67 | 69 |
68 template <typename T> | 70 template <typename T> |
69 struct OptionalStorage<T, true> { | 71 struct OptionalStorage<T, true> { |
70 constexpr OptionalStorage() {} | 72 // Initializing |empty_| here instead of using default member initializing |
| 73 // to avoid errors in g++ 4.8. |
| 74 constexpr OptionalStorage() : empty_('\0') {} |
71 | 75 |
72 constexpr explicit OptionalStorage(const T& value) | 76 constexpr explicit OptionalStorage(const T& value) |
73 : is_null_(false), value_(value) {} | 77 : is_null_(false), value_(value) {} |
74 | 78 |
75 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. | 79 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. |
76 explicit OptionalStorage(T&& value) | 80 explicit OptionalStorage(T&& value) |
77 : is_null_(false), value_(std::move(value)) {} | 81 : is_null_(false), value_(std::move(value)) {} |
78 | 82 |
79 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. | 83 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. |
80 template <class... Args> | 84 template <class... Args> |
81 explicit OptionalStorage(base::in_place_t, Args&&... args) | 85 explicit OptionalStorage(base::in_place_t, Args&&... args) |
82 : is_null_(false), value_(std::forward<Args>(args)...) {} | 86 : is_null_(false), value_(std::forward<Args>(args)...) {} |
83 | 87 |
84 // When T is trivially destructible (i.e. its destructor does nothing) there | 88 // When T is trivially destructible (i.e. its destructor does nothing) there |
85 // is no need to call it. Explicitly defaulting the destructor means it's not | 89 // is no need to call it. Explicitly defaulting the destructor means it's not |
86 // user-provided. Those two together make this destructor trivial. | 90 // user-provided. Those two together make this destructor trivial. |
87 ~OptionalStorage() = default; | 91 ~OptionalStorage() = default; |
88 | 92 |
89 bool is_null_ = true; | 93 bool is_null_ = true; |
90 union { | 94 union { |
91 // |empty_| exists so that the union will always be initialized, even when | 95 // |empty_| exists so that the union will always be initialized, even when |
92 // it doesn't contain a value. Not initializing it has been observed to | 96 // it doesn't contain a value. Union members must be initialized for the |
93 // trigger comiler warnings. | 97 // constructor to be 'constexpr'. |
94 char empty_ = '\0'; | 98 char empty_; |
95 T value_; | 99 T value_; |
96 }; | 100 }; |
97 }; | 101 }; |
98 | 102 |
99 } // namespace internal | 103 } // namespace internal |
100 | 104 |
101 // base::Optional is a Chromium version of the C++17 optional class: | 105 // base::Optional is a Chromium version of the C++17 optional class: |
102 // std::optional documentation: | 106 // std::optional documentation: |
103 // http://en.cppreference.com/w/cpp/utility/optional | 107 // http://en.cppreference.com/w/cpp/utility/optional |
104 // Chromium documentation: | 108 // Chromium documentation: |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 template <class T> | 497 template <class T> |
494 struct hash<base::Optional<T>> { | 498 struct hash<base::Optional<T>> { |
495 size_t operator()(const base::Optional<T>& opt) const { | 499 size_t operator()(const base::Optional<T>& opt) const { |
496 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); | 500 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); |
497 } | 501 } |
498 }; | 502 }; |
499 | 503 |
500 } // namespace std | 504 } // namespace std |
501 | 505 |
502 #endif // BASE_OPTIONAL_H_ | 506 #endif // BASE_OPTIONAL_H_ |
OLD | NEW |