forked from scylladb/seastar
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoptimized_optional.hh
104 lines (89 loc) · 3.13 KB
/
optimized_optional.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
* 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 "util/gcc6-concepts.hh"
#include "util/std-compat.hh"
#include <experimental/type_traits>
#include <iostream>
namespace seastar {
namespace stdx = std::experimental;
GCC6_CONCEPT(
template<typename T>
concept bool OptimizableOptional() {
return stdx::is_default_constructible_v<T>
&& stdx::is_nothrow_move_assignable_v<T>
&& 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(compat::nullopt_t) noexcept { }
optimized_optional(const T& obj) : _object(obj) { }
optimized_optional(T&& obj) noexcept : _object(std::move(obj)) { }
optimized_optional(compat::optional<T>&& obj) noexcept {
if (obj) {
_object = std::move(*obj);
}
}
optimized_optional(const optimized_optional&) = default;
optimized_optional(optimized_optional&&) = default;
optimized_optional& operator=(compat::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;
}
};
}