1 | /******************************************************************************* |
2 | * Copyright 2021 Intel Corporation |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | *******************************************************************************/ |
16 | |
17 | #ifndef COMMON_OPTIONAL_HPP |
18 | #define COMMON_OPTIONAL_HPP |
19 | |
20 | #include <cassert> |
21 | #include <memory> |
22 | #include <new> |
23 | #include <type_traits> |
24 | |
25 | namespace dnnl { |
26 | namespace impl { |
27 | namespace utils { |
28 | |
29 | // This is a simple version of the std::optional class |
30 | // When C++17 will be supported it is highly recommended |
31 | // to remove this class and start using std::optional instead. |
32 | |
33 | struct nullopt_t { |
34 | nullopt_t() = default; |
35 | }; |
36 | static constexpr nullopt_t nullopt {}; |
37 | |
38 | template <typename T> |
39 | class optional_t; |
40 | |
41 | template <typename T> |
42 | struct is_optional_t : public std::false_type {}; |
43 | template <typename T> |
44 | struct is_optional_t<optional_t<T>> : public std::true_type {}; |
45 | |
46 | template <class T> |
47 | class optional_t { |
48 | public: |
49 | static_assert(!std::is_lvalue_reference<T>::value, "" ); |
50 | static_assert(!std::is_rvalue_reference<T>::value, "" ); |
51 | static_assert(!std::is_const<T>::value, "" ); |
52 | static_assert(!std::is_volatile<T>::value, "" ); |
53 | static_assert(!is_optional_t<T>::value, "" ); |
54 | |
55 | optional_t(const nullopt_t nullopt) : has_value_(false), dummy {} {} |
56 | optional_t(T object) : has_value_(true), value_(object) {} |
57 | optional_t(const optional_t &other) |
58 | : has_value_(other.has_value_), dummy {} { |
59 | if (has_value_) new (std::addressof(value_)) T(other.value_); |
60 | } |
61 | optional_t(optional_t<T> &&other) noexcept |
62 | : has_value_(other.has_value_), dummy {} { |
63 | if (has_value_) new (std::addressof(value_)) T(std::move(other.value_)); |
64 | } |
65 | ~optional_t() { |
66 | if (has_value_) value_.~T(); |
67 | } |
68 | |
69 | optional_t &operator=(const nullopt_t nullopt) { |
70 | if (has_value_) value_.~T(); |
71 | has_value_ = false; |
72 | } |
73 | optional_t &operator=(const optional_t &other) { |
74 | if (this == &other) return *this; |
75 | if (has_value_) value_.~T(); |
76 | has_value_ = other.has_value_; |
77 | if (has_value_) value_ = other.value_; |
78 | return *this; |
79 | } |
80 | optional_t &operator=(optional_t &&other) { |
81 | if (this == &other) return *this; |
82 | if (has_value_) value_.~T(); |
83 | has_value_ = other.has_value_; |
84 | if (has_value_) value_ = std::move(other.value_); |
85 | return *this; |
86 | } |
87 | |
88 | const T *operator->() const { |
89 | assert(has_value_); |
90 | return &value_; |
91 | } |
92 | T *operator->() { |
93 | assert(has_value_); |
94 | return &value_; |
95 | } |
96 | const T &operator*() const { |
97 | assert(has_value_); |
98 | return value_; |
99 | } |
100 | T &operator*() { |
101 | assert(has_value_); |
102 | return value_; |
103 | } |
104 | operator bool() const { return has_value_; } |
105 | |
106 | T value_or(T &&returned_value) { |
107 | return has_value_ ? value_ : returned_value; |
108 | } |
109 | T value_or(T &&returned_value) const { |
110 | return has_value_ ? value_ : returned_value; |
111 | } |
112 | const T &value() const { |
113 | assert(has_value_); |
114 | return value_; |
115 | } |
116 | T &value() { |
117 | assert(has_value_); |
118 | return value_; |
119 | } |
120 | bool has_value() const { return has_value_; } |
121 | void reset() { |
122 | if (has_value_) value_.~T(); |
123 | has_value_ = false; |
124 | } |
125 | |
126 | private: |
127 | bool has_value_; |
128 | |
129 | union { |
130 | char dummy; |
131 | T value_; |
132 | }; |
133 | }; |
134 | |
135 | } // namespace utils |
136 | } // namespace impl |
137 | } // namespace dnnl |
138 | |
139 | #endif |
140 | |