staticlib_support  1.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
optional.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017, alex at staticlibs.net
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 /*
18  * File: optional.hpp
19  * Author: alex
20  *
21  * Created on February 4, 2017, 7:40 PM
22  */
23 
24 #ifndef STATICLIB_SUPPORT_OPTIONAL_HPP
25 #define STATICLIB_SUPPORT_OPTIONAL_HPP
26 
27 #include <type_traits>
28 
29 #include "staticlib/config.hpp"
30 
32 
33 namespace staticlib {
34 namespace support {
35 
40 public:
45  exception("Invalid attempt to access non-initialized value of 'optional' object") { }
46 };
47 
52 template<typename T>
53 class optional {
57  typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type value_space;
58 
62  T* value_ptr = nullptr;
63 
64 public:
65 
69  optional() { }
70 
76  explicit optional(T&& value) :
77  value_ptr(new (std::addressof(value_space)) T(std::move(value))) { }
78 
82  optional(const optional&) = delete;
83 
87  optional& operator=(const optional&) = delete;
88 
94  optional(optional&& other) STATICLIB_NOEXCEPT {
95  if(other.has_value()) {
96  value_ptr = new (std::addressof(value_space)) T(std::move(other.value()));
97  other.reset();
98  }
99  }
100 
107  optional& operator=(optional&& other) STATICLIB_NOEXCEPT {
108  reset();
109  if (other.has_value()) {
110  value_ptr = new (std::addressof(value_space)) T(std::move(other.value()));
111  other.reset();
112  }
113  return *this;
114  }
115 
119  ~optional() STATICLIB_NOEXCEPT {
120  if (has_value()) {
121  value_ptr->~T();
122  }
123  }
124 
130  explicit operator bool() const {
131  return has_value();
132  }
133 
139  bool has_value() const {
140  return nullptr != value_ptr;
141  }
142 
149  T& value() {
150  if(has_value()) {
151  return *value_ptr;
152  } else {
154  }
155  }
156 
163  const T& value() const {
164  if (has_value()) {
165  return *value_ptr;
166  } else {
168  }
169  }
170 
177  T value_or(T&& default_value) const {
178  if (has_value()) {
179  // copy constructor called
180  return *value_ptr;
181  }
182  return std::move(default_value);
183  }
184 
193  T value_or(T&& default_value) {
194  if (has_value()) {
195  return std::move(*value_ptr);
196  }
197  return std::move(default_value);
198  }
199 
203  void reset() {
204  if (has_value()) {
205  value_ptr->~T();
206  }
207  value_ptr = nullptr;
208  }
209 
210 };
211 
218 template<typename T>
220  return optional<T>(std::move(value));
221 }
222 
223 } // namespace
224 }
225 
226 
227 #endif /* STATICLIB_SUPPORT_OPTIONAL_HPP */
228