Electroneum
expect< T > Class Template Reference

#include <expect.h>

Public Types

using value_type = T
 
using error_type = std::error_code
 

Public Member Functions

 expect ()=delete
 
 expect (std::error_code const &code) noexcept
 
 expect (T val) noexcept(std::is_nothrow_move_constructible< T >())
 Store a value, val, in the expect object. More...
 
 expect (expect const &src) noexcept(std::is_nothrow_copy_constructible< T >())
 
template<typename U , typename = detail::enable_if<is_convertible<U const&>()>>
 expect (expect< U > const &src) noexcept(std::is_nothrow_constructible< T, U const &>())
 Copy conversion from U to T. More...
 
 expect (expect &&src) noexcept(std::is_nothrow_move_constructible< T >())
 
template<typename U , typename = detail::enable_if<is_convertible<U>()>>
 expect (expect< U > &&src) noexcept(std::is_nothrow_constructible< T, U >())
 Move conversion from U to T. More...
 
 ~expect () noexcept
 
expectoperator= (expect const &src) noexcept(std::is_nothrow_copy_constructible< T >() &&std::is_nothrow_copy_assignable< T >())
 
expectoperator= (expect &&src) noexcept(std::is_nothrow_move_constructible< T >() &&std::is_nothrow_move_assignable< T >())
 
 operator bool () const noexcept
 
bool has_error () const noexcept
 
bool has_value () const noexcept
 
std::error_code error () const noexcept
 
Tvalue () &
 
T const & value () const &
 
T && value () &&
 
Toperator-> () noexcept
 
T const * operator-> () const noexcept
 
Toperator* () noexcept
 
T const & operator* () const noexcept
 
template<typename U >
bool equal (expect< U > const &rhs) const noexcept(noexcept(*std::declval< expect< T >>()== *rhs))
 
bool equal (std::error_code const &rhs) const noexcept
 
template<typename U , typename = detail::enable_if<!std::is_constructible<std::error_code, U>::value>>
bool equal (U const &rhs) const noexcept(noexcept(*std::declval< expect< T >>()==rhs))
 
bool matches (std::error_condition const &rhs) const noexcept
 

Detailed Description

template<typename T>
class expect< T >

expect<T> is a value or error implementation, similar to Rust std::result or various C++ proposals (boost::expected, boost::outcome). This implementation currently has a strict error type, std::error_code, and a templated value type T. expect<T> is implicitly convertible from T or std::error_code, and one expect<T> object type is implicitly convertible to another expect<U> object iff the destination value type can be implicitly constructed from the source value type (i.e. struct U { ... U(T src) { ...} ... };).

operator== and operator!= are the only comparison operators provided; comparison between different value types is allowed provided the two values types have a operator== defined between them (i.e. assert(expect<int>{100} == expect<short>{100});). Comparisons can also be done against std::error_code objects or error code enums directly (i.e. assert(expect<int>{make_error_code(common_error::kInvalidArgument)} == error::kInvalidArgument)). Comparison of default constructed std::error_code will always fail. "Generic" comparisons can be done with std::error_condition via the matches method only (i.e. assert(expect<int>{make_error_code{common_error::kInvalidErrorCode}.matches(std::errc::invalid_argument))), operator== and operator!= will not work with std::errc or std::error_condition. A comparison with matches is more expensive because an equivalency between error categories is computed, but is recommended when an error can be one of several categories (this is going to be the case in nearly every situation when calling a function from another C++ struct/class).

expect<void> is a special case with no stored value. It is used by functions that can fail, but otherwise would return void. It is useful for consistency; all macros, standalone functions, and comparison operators work with expect<void>.

Note
See src/common/error.h for creating a custom error enum.

Definition at line 70 of file expect.h.

Member Typedef Documentation

◆ error_type

template<typename T>
using expect< T >::error_type = std::error_code

Definition at line 175 of file expect.h.

◆ value_type

template<typename T>
using expect< T >::value_type = T

Definition at line 174 of file expect.h.

Constructor & Destructor Documentation

◆ expect() [1/7]

template<typename T>
expect< T >::expect ( )
delete

◆ expect() [2/7]

template<typename T>
expect< T >::expect ( std::error_code const &  code)
inlinenoexcept

Store an error, code, in the expect object. If code creates a std::error_code object whose .value() == 0, then error() will be set to common_error::kInvalidErrorCode.

Definition at line 182 of file expect.h.

183  : code_(code), storage_()
184  {
185  if (!has_error())
186  code_ = ::common_error::kInvalidErrorCode;
187  }
bool has_error() const noexcept
Definition: expect.h:270
Here is the call graph for this function:

◆ expect() [3/7]

template<typename T>
expect< T >::expect ( T  val)
inlinenoexcept

Store a value, val, in the expect object.

Definition at line 190 of file expect.h.

191  : code_(), storage_()
192  {
193  store(std::move(val));
194  }
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:

◆ expect() [4/7]

template<typename T>
expect< T >::expect ( expect< T > const &  src)
inlinenoexcept

Definition at line 196 of file expect.h.

197  : code_(src.error()), storage_()
198  {
199  if (src.has_value())
200  store(src.get());
201  }

◆ expect() [5/7]

template<typename T>
template<typename U , typename = detail::enable_if<is_convertible<U const&>()>>
expect< T >::expect ( expect< U > const &  src)
inlinenoexcept

Copy conversion from U to T.

Definition at line 205 of file expect.h.

206  : code_(src.error()), storage_()
207  {
208  if (src.has_value())
209  store(*src);
210  }
bool has_value() const noexcept
Definition: expect.h:273
std::error_code error() const noexcept
Definition: expect.h:276

◆ expect() [6/7]

template<typename T>
expect< T >::expect ( expect< T > &&  src)
inlinenoexcept

Definition at line 212 of file expect.h.

213  : code_(src.error()), storage_()
214  {
215  if (src.has_value())
216  store(std::move(src.get()));
217  }
bool has_value() const noexcept
Definition: expect.h:273
std::error_code error() const noexcept
Definition: expect.h:276
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:

◆ expect() [7/7]

template<typename T>
template<typename U , typename = detail::enable_if<is_convertible<U>()>>
expect< T >::expect ( expect< U > &&  src)
inlinenoexcept

Move conversion from U to T.

Definition at line 221 of file expect.h.

222  : code_(src.error()), storage_()
223  {
224  if (src.has_value())
225  store(std::move(*src));
226  }
bool has_value() const noexcept
Definition: expect.h:273
std::error_code error() const noexcept
Definition: expect.h:276
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:

◆ ~expect()

template<typename T>
expect< T >::~expect ( )
inlinenoexcept

Definition at line 228 of file expect.h.

229  {
230  if (has_value())
231  get().~T();
232  }
const uint32_t T[512]
bool has_value() const noexcept
Definition: expect.h:273
Here is the call graph for this function:

Member Function Documentation

◆ equal() [1/3]

template<typename T>
template<typename U >
bool expect< T >::equal ( expect< U > const &  rhs) const
inlinenoexcept
Note
This function is noexcept when U == T is noexcept.
Returns
True if has_value() == rhs.has_value() and if values or errors are equal.

Definition at line 314 of file expect.h.

315  {
316  return has_value() && rhs.has_value() ?
317  get() == *rhs : error() == rhs.error();
318  }
bool has_value() const noexcept
Definition: expect.h:273
std::error_code error() const noexcept
Definition: expect.h:276
Here is the call graph for this function:

◆ equal() [2/3]

template<typename T>
bool expect< T >::equal ( std::error_code const &  rhs) const
inlinenoexcept
Returns
False if has_value(), otherwise error() == rhs.

Definition at line 321 of file expect.h.

322  {
323  return has_error() && error() == rhs;
324  }
std::error_code error() const noexcept
Definition: expect.h:276
bool has_error() const noexcept
Definition: expect.h:270
Here is the call graph for this function:

◆ equal() [3/3]

template<typename T>
template<typename U , typename = detail::enable_if<!std::is_constructible<std::error_code, U>::value>>
bool expect< T >::equal ( U const &  rhs) const
inlinenoexcept
Note
This function is noexcept when U == T is noexcept.
Returns
False if has_error(), otherwise value() == rhs.

Definition at line 331 of file expect.h.

332  {
333  return has_value() && get() == rhs;
334  }
bool has_value() const noexcept
Definition: expect.h:273
Here is the call graph for this function:

◆ error()

template<typename T>
std::error_code expect< T >::error ( ) const
inlinenoexcept
Returns
Error - always safe to call. Empty when !has_error().

Definition at line 276 of file expect.h.

276 { return code_; }
Here is the caller graph for this function:

◆ has_error()

template<typename T>
bool expect< T >::has_error ( ) const
inlinenoexcept
Returns
True if this is storing an error instead of a value.

Definition at line 270 of file expect.h.

270 { return bool(code_); }
int bool
Definition: stdbool.h:36
Here is the caller graph for this function:

◆ has_value()

template<typename T>
bool expect< T >::has_value ( ) const
inlinenoexcept
Returns
True if this is storing a value instead of an error.

Definition at line 273 of file expect.h.

273 { return !has_error(); }
bool has_error() const noexcept
Definition: expect.h:270
Here is the call graph for this function:
Here is the caller graph for this function:

◆ matches()

template<typename T>
bool expect< T >::matches ( std::error_condition const &  rhs) const
inlinenoexcept
Returns
False if has_value(), otherwise error() == rhs.

Definition at line 337 of file expect.h.

338  {
339  return has_error() && error() == rhs;
340  }
std::error_code error() const noexcept
Definition: expect.h:276
bool has_error() const noexcept
Definition: expect.h:270
Here is the call graph for this function:

◆ operator bool()

template<typename T>
expect< T >::operator bool ( ) const
inlineexplicitnoexcept
Returns
True if this is storing a value instead of an error.

Definition at line 267 of file expect.h.

267 { return has_value(); }
bool has_value() const noexcept
Definition: expect.h:273
Here is the call graph for this function:

◆ operator*() [1/2]

template<typename T>
T& expect< T >::operator* ( )
inlinenoexcept
Returns
Value,
Precondition
has_value().

Definition at line 305 of file expect.h.

305 { return get(); }

◆ operator*() [2/2]

template<typename T>
T const& expect< T >::operator* ( ) const
inlinenoexcept
Returns
Value,
Precondition
has_value().

Definition at line 307 of file expect.h.

307 { return get(); }

◆ operator->() [1/2]

template<typename T>
T* expect< T >::operator-> ( )
inlinenoexcept
Returns
Value,
Precondition
has_value().

Definition at line 301 of file expect.h.

301 { return std::addressof(get()); }

◆ operator->() [2/2]

template<typename T>
T const* expect< T >::operator-> ( ) const
inlinenoexcept
Returns
Value,
Precondition
has_value().

Definition at line 303 of file expect.h.

303 { return std::addressof(get()); }

◆ operator=() [1/2]

template<typename T>
expect& expect< T >::operator= ( expect< T > const &  src)
inlinenoexcept

Definition at line 234 of file expect.h.

235  {
236  if (this != std::addressof(src))
237  {
238  if (has_value() && src.has_value())
239  get() = src.get();
240  else if (has_value())
241  get().~T();
242  else if (src.has_value())
243  store(src.get());
244  code_ = src.error();
245  }
246  return *this;
247  }
const uint32_t T[512]
bool has_value() const noexcept
Definition: expect.h:273
Here is the call graph for this function:

◆ operator=() [2/2]

template<typename T>
expect& expect< T >::operator= ( expect< T > &&  src)
inlinenoexcept

Move src into this. If src.has_value() && addressof(src) != this then `src.value() will be in a "moved from state".

Definition at line 251 of file expect.h.

252  {
253  if (this != std::addressof(src))
254  {
255  if (has_value() && src.has_value())
256  get() = std::move(src.get());
257  else if (has_value())
258  get().~T();
259  else if (src.has_value())
260  store(std::move(src.get()));
261  code_ = src.error();
262  }
263  return *this;
264  }
bool has_value() const noexcept
Definition: expect.h:273
std::error_code error() const noexcept
Definition: expect.h:276
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:

◆ value() [1/3]

template<typename T>
T& expect< T >::value ( void  ) &
inline
Returns
Value if has_value() otherwise
Exceptions
<tt>std::system_error{error()}</tt>.

Definition at line 279 of file expect.h.

280  {
281  maybe_throw();
282  return get();
283  }
Here is the caller graph for this function:

◆ value() [2/3]

template<typename T>
T const& expect< T >::value ( void  ) const &
inline
Returns
Value if has_value() otherwise
Exceptions
<tt>std::system_error{error()}</tt>.

Definition at line 286 of file expect.h.

287  {
288  maybe_throw();
289  return get();
290  }

◆ value() [3/3]

template<typename T>
T&& expect< T >::value ( void  ) &&
inline

Same as other overloads, but expressions such as foo(bar().value()) will automatically perform moves with no copies.

Definition at line 294 of file expect.h.

295  {
296  maybe_throw();
297  return std::move(get());
298  }
const T & move(const T &t)
Definition: gtest-port.h:1317
Here is the call graph for this function:

The documentation for this class was generated from the following file: