openPMD-api
Option.hpp
1 /* Copyright 2020-2021 Franz Poeschel
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #pragma once
23 
24 #include "VariantSrc.hpp"
25 
26 #include <type_traits>
27 #include <utility> // std::forward, std::move
28 
29 namespace openPMD
30 {
31 namespace auxiliary
32 {
33  namespace detail
34  {
35  struct Empty
36  {};
37  } // namespace detail
38 
44  template <typename T>
45  class Option
46  {
47  using data_t = variantSrc::variant<T, detail::Empty>;
48  data_t m_data;
49 
50  public:
53  explicit Option() : m_data(detail::Empty())
54  {}
55 
60  Option(T data) : m_data(std::move(data))
61  {}
62 
63  Option(Option const &other) = default;
64 
65  Option &operator=(Option &&other)
66  {
67  if (other.has_value())
68  {
69  m_data.template emplace<0>(std::move(other.get()));
70  }
71  else
72  {
73  m_data.template emplace<1>(detail::Empty());
74  }
75  return *this;
76  }
77 
78  Option &operator=(Option const &other)
79  {
80  if (other.has_value())
81  {
82  m_data.template emplace<0>(other.get());
83  }
84  else
85  {
86  m_data.template emplace<1>(detail::Empty());
87  }
88  return *this;
89  }
90 
91  bool operator==(Option const &other) const
92  {
93  if (has_value())
94  {
95  return !other.has_value();
96  }
97  else
98  {
99  if (!other.has_value())
100  {
101  return false;
102  }
103  else
104  {
105  return get() == other.get();
106  }
107  }
108  }
109 
110  bool operator!=(Option const &other) const
111  {
112  return !(*this == other);
113  }
114 
118  bool has_value() const
119  {
120  return m_data.index() == 0;
121  }
122 
126  operator bool() const
127  {
128  return has_value();
129  }
130 
137  T const &get() const
138  {
139  return variantSrc::template get<T>(m_data);
140  }
141 
148  T &get()
149  {
150  return variantSrc::template get<T>(m_data);
151  }
152  };
153 
154  template <typename T>
155  Option<typename std::decay<T>::type> makeOption(T &&val)
156  {
157  return Option<typename std::decay<T>::type>(std::forward<T>(val));
158  }
159 } // namespace auxiliary
160 } // namespace openPMD
Option(T data)
Create a full Option.
Definition: Option.hpp:60
STL namespace.
Option()
Create an empty Option.
Definition: Option.hpp:53
Definition: Container.cpp:50
Simple Option type based on variantSrc::variant.
Definition: Option.hpp:45
Public definitions of openPMD-api.
Definition: Date.cpp:28
T const & get() const
Access the emplaced object if one is present.
Definition: Option.hpp:137
Definition: Option.hpp:35
bool has_value() const
Definition: Option.hpp:118