diff options
Diffstat (limited to '')
-rw-r--r-- | src/seastar/include/seastar/util/optimized_optional.hh | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/seastar/include/seastar/util/optimized_optional.hh b/src/seastar/include/seastar/util/optimized_optional.hh new file mode 100644 index 000000000..60febceae --- /dev/null +++ b/src/seastar/include/seastar/util/optimized_optional.hh @@ -0,0 +1,101 @@ +/* + * This file is open source software, licensed to you under the terms + * of the Apache License, Version 2.0 (the "License"). See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. You may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/* + * Copyright (C) 2017 ScyllaDB + */ + +#pragma once + +#include <seastar/util/concepts.hh> +#include <seastar/util/std-compat.hh> + +#include <type_traits> +#include <iostream> + +namespace seastar { + +SEASTAR_CONCEPT( + +template<typename T> +concept OptimizableOptional = + std::is_default_constructible<T>::value + && std::is_nothrow_move_assignable<T>::value + && requires(const T& obj) { + { bool(obj) } noexcept; + }; + +) + +/// \c optimized_optional<> is intended mainly for use with classes that store +/// their data externally and expect pointer to this data to be always non-null. +/// In such case there is no real need for another flag signifying whether +/// the optional is engaged. +template<typename T> +class optimized_optional { + T _object; +public: + optimized_optional() = default; + optimized_optional(std::nullopt_t) noexcept { } + optimized_optional(const T& obj) : _object(obj) { } + optimized_optional(T&& obj) noexcept : _object(std::move(obj)) { } + optimized_optional(std::optional<T>&& obj) noexcept { + if (obj) { + _object = std::move(*obj); + } + } + optimized_optional(const optimized_optional&) = default; + optimized_optional(optimized_optional&&) = default; + + optimized_optional& operator=(std::nullopt_t) noexcept { + _object = T(); + return *this; + } + template<typename U> + std::enable_if_t<std::is_same<std::decay_t<U>, T>::value, optimized_optional&> + operator=(U&& obj) noexcept { + _object = std::forward<U>(obj); + return *this; + } + optimized_optional& operator=(const optimized_optional&) = default; + optimized_optional& operator=(optimized_optional&&) = default; + + explicit operator bool() const noexcept { + return bool(_object); + } + + T* operator->() noexcept { return &_object; } + const T* operator->() const noexcept { return &_object; } + + T& operator*() noexcept { return _object; } + const T& operator*() const noexcept { return _object; } + + bool operator==(const optimized_optional& other) const { + return _object == other._object; + } + bool operator!=(const optimized_optional& other) const { + return _object != other._object; + } + friend std::ostream& operator<<(std::ostream& out, const optimized_optional& opt) { + if (!opt) { + return out << "null"; + } + return out << *opt; + } +}; + +} |