SPH
Expected.h
Go to the documentation of this file.
1 #pragma once
2 
7 
9 
11 
12 
13 struct UnexpectedTag {};
15 
24 template <typename Type, typename Error = std::string>
25 class Expected {
26 private:
28  struct UnexpectedWrapper {
29  Error error;
30  };
31 
32  // first type is dummy to use the default constructor of variant
34 
35 public:
41  data.template emplace<Type>();
42  }
43 
45  template <typename T, typename = std::enable_if_t<std::is_constructible<Type, T>::value>>
46  Expected(T&& value) {
47  data.template emplace<Type>(std::forward<T>(value));
48  }
49 
51  template <typename TError, typename = std::enable_if_t<std::is_constructible<Error, TError>::value>>
53  data.template emplace<UnexpectedWrapper>(UnexpectedWrapper{ std::forward<TError>(error) });
54  }
55 
57  explicit operator bool() const {
58  return isExpected();
59  }
60 
62  bool operator!() const {
63  return !isExpected();
64  }
65 
69  Type& value() {
70  SPH_ASSERT(isExpected());
71  return data.template get<Type>();
72  }
73 
77  const Type& value() const {
78  SPH_ASSERT(isExpected());
79  return data.template get<Type>();
80  }
81 
83  Type valueOr(const Type& other) const {
84  if (isExpected()) {
85  return this->value();
86  } else {
87  return other;
88  }
89  }
90 
94  const Error& error() const {
95  SPH_ASSERT(!isExpected());
96  return data.template get<UnexpectedWrapper>().error;
97  }
98 
102  Type* operator->() {
103  SPH_ASSERT(isExpected());
104  return &value();
105  }
106 
108  const Type* operator->() const {
109  SPH_ASSERT(isExpected());
110  return &value();
111  }
112 
113 private:
114  bool isExpected() const {
115  return data.getTypeIdx() == 1;
116  }
117 };
118 
124 template <typename T, typename = decltype(std::declval<std::ostream&>() << std::declval<T>())>
125 inline std::ostream& operator<<(std::ostream& stream, const Expected<T>& expected) {
126  if (expected) {
127  stream << expected.value();
128  } else {
129  stream << expected.error();
130  }
131  return stream;
132 }
133 
137 template <typename Type>
138 Expected<Type> makeUnexpected(const std::string& error) {
139  return Expected<Type>(UNEXPECTED, error);
140 }
141 
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
const UnexpectedTag UNEXPECTED
Definition: Expected.h:14
Expected< Type > makeUnexpected(const std::string &error)
Constructs an unexpected value of given type, given error message as std::string.
Definition: Expected.h:138
#define NAMESPACE_SPH_END
Definition: Object.h:12
Object capable of storing values of different types.
Wrapper of type that either contains a value of given type, or an error message.
Definition: Expected.h:25
Expected(T &&value)
Constructs an expected value.
Definition: Expected.h:46
Expected(UnexpectedTag, TError &&error)
Constructs an unexpected value.
Definition: Expected.h:52
Type * operator->()
Operator -> for convenient access to member variables and functions of expected value.
Definition: Expected.h:102
const Error & error() const
Returns the error message.
Definition: Expected.h:94
bool operator!() const
Negation operator, returns true if object does NOT contain expected value.
Definition: Expected.h:62
const Type & value() const
Returns the const reference to expected value.
Definition: Expected.h:77
Type valueOr(const Type &other) const
Returns the expected value or given alternative if the object contains unexpected value.
Definition: Expected.h:83
Expected()
Construct the expected value using default constructor.
Definition: Expected.h:40
Type & value()
Returns the reference to expected value.
Definition: Expected.h:69
const Type * operator->() const
operator->()
Definition: Expected.h:108
INLINE Size getTypeIdx() const
Returns index of type currently stored in variant.
Definition: Variant.h:310