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 <utility> // std::forward, std::move
27 #include <type_traits>
28 
29 
30 namespace openPMD
31 {
32 namespace auxiliary
33 {
34  namespace detail
35  {
36  struct Empty
37  {
38  };
39  } // namespace detail
40 
46  template< typename T >
47  class Option
48  {
49  using data_t = variantSrc::variant< T, detail::Empty >;
50  data_t m_data;
51 
52  public:
55  explicit Option() : m_data( detail::Empty() )
56  {
57  }
58 
63  Option( T data ) : m_data( std::move( data ) )
64  {
65  }
66 
67  Option( Option const & other ) = default;
68 
69  Option &
70  operator=( Option && other )
71  {
72  if( other.has_value() )
73  {
74  m_data.template emplace< 0 >( std::move( other.get() ) );
75  }
76  else
77  {
78  m_data.template emplace< 1 >( detail::Empty() );
79  }
80  return *this;
81  }
82 
83  Option &
84  operator=( Option const & other )
85  {
86  if( other.has_value() )
87  {
88  m_data.template emplace< 0 >( other.get() );
89  }
90  else
91  {
92  m_data.template emplace< 1 >( detail::Empty() );
93  }
94  return *this;
95  }
96 
97  bool
98  operator==( Option const & other ) const
99  {
100  if( has_value() )
101  {
102  return !other.has_value();
103  }
104  else
105  {
106  if( !other.has_value() )
107  {
108  return false;
109  }
110  else
111  {
112  return get() == other.get();
113  }
114  }
115  }
116 
117  bool
118  operator!=( Option const & other ) const
119  {
120  return !( *this == other );
121  }
122 
126  bool
127  has_value() const
128  {
129  return m_data.index() == 0;
130  }
131 
135  operator bool() const
136  {
137  return has_value();
138  }
139 
146  T const &
147  get() const
148  {
149  return variantSrc::template get< T >( m_data );
150  }
151 
158  T &
159  get()
160  {
161  return variantSrc::template get< T >( m_data );
162  }
163  };
164 
165  template< typename T >
166  Option< typename std::decay< T >::type >
167  makeOption( T && val )
168  {
169  return Option< typename std::decay< T >::type >(
170  std::forward< T >( val ) );
171  }
172 } // namespace auxiliary
173 } // namespace openPMD
openPMD::auxiliary::Option::Option
Option()
Create an empty Option.
Definition: Option.hpp:55
openPMD::auxiliary::Option::has_value
bool has_value() const
Definition: Option.hpp:127
openPMD::UnitDimension::T
@ T
time
openPMD::auxiliary::Option
Simple Option type based on variantSrc::variant.
Definition: Option.hpp:47
openPMD::auxiliary::detail::Empty
Definition: Option.hpp:36
openPMD
Public definitions of openPMD-api.
Definition: Date.cpp:29
openPMD::auxiliary::Option::get
T & get()
Access the emplaced object if one is present.
Definition: Option.hpp:159
openPMD::auxiliary::Option::get
const T & get() const
Access the emplaced object if one is present.
Definition: Option.hpp:147
openPMD::auxiliary::Option::Option
Option(T data)
Create a full Option.
Definition: Option.hpp:63