Flex  0.17.9
result.h
Go to the documentation of this file.
1 
16 #ifndef UTILS_RESULT_H_
17 #define UTILS_RESULT_H_
18 
19 #include <filesystem>
20 #include <iostream>
21 #include <string>
22 #include <vector>
23 
24 #include "flex/utils/error_pb/interactive.pb.h"
25 
26 #include "glog/logging.h"
27 
28 namespace gs {
29 
30 using StatusCode = gs::flex::interactive::Code;
31 
32 class Status {
33  public:
34  Status() noexcept;
35  Status(StatusCode error_code) noexcept;
36  Status(StatusCode error_code, std::string&& error_msg) noexcept;
37  Status(StatusCode error_code, const std::string& error_msg) noexcept;
38  bool ok() const;
39  std::string error_message() const;
40  StatusCode error_code() const;
41 
42  static Status OK();
43 
44  std::string ToString() const;
45 
46  private:
48  std::string error_msg_;
49 };
50 
51 // Define a class with name Result<T>, which is a template class
52 // Stores the result of a function that may fail.
53 // If the function succeeds, the result contains the value returned by the
54 // function. If the function fails, the result contains the error message. The
55 // result is always valid and can be queried for success or failure. If the
56 // result is successful, the value can be obtained by calling the value()
57 // method. If the result fails, the error message can be obtained by calling the
58 // error() method. The result can be converted to bool, and the result is true
59 // if the result is successful. The result can be converted to bool, and the
60 // result is false if the result fails.
61 template <typename T>
62 class Result {
63  public:
64  using ValueType = T;
68  : status_(StatusCode::OK), value_(std::move(value)) {}
70  : status_(status), value_(std::move(value)) {}
71 
73 
75  : status_(status), value_(value) {}
76 
77  Result(StatusCode code, const std::string& error_msg, const ValueType& value)
78  : status_(code, error_msg), value_(value) {}
79 
80  Result(StatusCode code, std::string&& error_msg, const ValueType& value)
81  : status_(code, std::move(error_msg)), value_(value) {}
82 
83  bool ok() const noexcept { return status_.ok(); }
84 
85  const Status& status() const noexcept { return status_; }
86  ValueType& value() noexcept { return value_; }
87 
88  // return rvalue
89  ValueType&& move_value() noexcept { return std::move(value_); }
90 
91  private:
94 };
95 
96 template <typename T>
97 struct is_gs_result_type : std::false_type {};
98 
99 template <typename T>
100 struct is_gs_result_type<Result<T>> : std::true_type {};
101 
102 template <typename T>
103 struct is_gs_status_type : std::false_type {};
104 
105 template <>
106 struct is_gs_status_type<Status> : std::true_type {};
107 
108 // define a macro, which checks the return status of a function, if ok, continue
109 // to execute, otherwise, return the status.
110 // the macro accept the calling code of a function, and the function name.
111 #define RETURN_IF_NOT_OK(expr) \
112  do { \
113  auto status = (expr); \
114  if (!status.ok()) { \
115  return status; \
116  } \
117  } while (0)
118 
119 // a Macro automatically assign the return value of a function, which returns
120 // result to a variable, and check the status of the result, if ok, continue to
121 // execute, otherwise, return the status. the macro accept the calling code of a
122 // function, the function name, and the variable name.
123 // reference:
124 // https://github.com/boostorg/leaf/blob/develop/include/boost/leaf/error.hpp
125 #define ASSIGN_AND_RETURN_IF_RESULT_NOT_OK(var, expr) \
126  { \
127  auto&& FLEX_TMP_VAR = expr; \
128  static_assert( \
129  ::gs::is_gs_result_type< \
130  typename std::decay<decltype(FLEX_TMP_VAR)>::type>::value, \
131  "The expression must return a Result type"); \
132  if (!FLEX_TMP_VAR.ok()) { \
133  return FLEX_TMP_VAR; \
134  } \
135  var = std::forward<decltype(FLEX_TMP_VAR)>(FLEX_TMP_VAR).move_value(); \
136  }
137 
138 #define ASSIGN_AND_RETURN_IF_STATUS_NOT_OK(var, expr) \
139  { \
140  auto&& FLEX_TMP_VAR = expr; \
141  static_assert( \
142  ::gs::is_gs_status_type< \
143  typename std::decay<decltype(FLEX_TMP_VAR)>::type>::value, \
144  "The expression must return a Status type"); \
145  if (!FLEX_TMP_VAR.ok()) { \
146  return FLEX_TMP_VAR; \
147  } \
148  var = std::forward<decltype(FLEX_TMP_VAR)>(FLEX_TMP_VAR).move_value(); \
149  }
150 
151 // A Marco automatically use a auto variable to store the return value of a
152 // function, which returns result, and check the status of the result, if ok,
153 // continue to execute, otherwise, return the status. the macro accept the
154 // calling code of a function, the function name, and the variable name.
155 #define FLEX_AUTO(var, expr) ASSIGN_AND_RETURN_IF_NOT_OK(auto var, expr)
156 
157 // Return boost::leaf::error object with error code and error message,
158 
159 #define RETURN_FLEX_LEAF_ERROR(code, msg) \
160  return ::boost::leaf::new_error( \
161  gs::Status(::gs::flex::interactive::Code::code, msg))
162 
163 } // namespace gs
164 
165 namespace std {
166 inline std::string to_string(const gs::flex::interactive::Code& status) {
167  // format the code into 0x-xxxx, where multiple zeros are prepend to the code
168  std::stringstream ss;
169  ss << "05-" << std::setw(4) << std::setfill('0')
170  << static_cast<int32_t>(status);
171  return ss.str();
172 }
173 } // namespace std
174 
175 #endif // UTILS_RESULT_H_
gs::Status::ok
bool ok() const
Definition: result.cc:33
gs::Result::value_
ValueType value_
Definition: result.h:93
gs::Result
Definition: result.h:62
gs::Result::move_value
ValueType && move_value() noexcept
Definition: result.h:89
gs::Status::Status
Status() noexcept
Definition: result.cc:19
gs::Result::Result
Result(const Status &status)
Definition: result.h:72
std::to_string
std::string to_string(const gs::flex::interactive::Code &status)
Definition: result.h:166
gs::Status::OK
static Status OK()
Definition: result.cc:35
gs
Definition: adj_list.h:23
gs::Result::Result
Result(const Status &status, ValueType &&value)
Definition: result.h:69
gs::Status::error_msg_
std::string error_msg_
Definition: result.h:48
gs::Status::error_code
StatusCode error_code() const
Definition: result.cc:31
gs::Result::value
ValueType & value() noexcept
Definition: result.h:86
gs::Status::error_code_
StatusCode error_code_
Definition: result.h:47
gs::Result::Result
Result(const ValueType &value)
Definition: result.h:66
gs::Status
Definition: result.h:32
gs::is_gs_status_type
Definition: result.h:103
gs::is_gs_result_type
Definition: result.h:97
gs::Result::status
const Status & status() const noexcept
Definition: result.h:85
gs::Result::ok
bool ok() const noexcept
Definition: result.h:83
gs::Result::Result
Result(ValueType &&value)
Definition: result.h:67
std
Definition: loading_config.h:232
gs::Status::ToString
std::string ToString() const
Definition: result.cc:37
gs::StatusCode
gs::flex::interactive::Code StatusCode
Definition: result.h:30
gs::Result::Result
Result()
Definition: result.h:65
gs::Status::error_message
std::string error_message() const
Definition: result.cc:29
gs::Result::Result
Result(StatusCode code, std::string &&error_msg, const ValueType &value)
Definition: result.h:80
gs::Result::Result
Result(const Status &status, const ValueType &value)
Definition: result.h:74
gs::Result::Result
Result(StatusCode code, const std::string &error_msg, const ValueType &value)
Definition: result.h:77
gs::Result::status_
Status status_
Definition: result.h:92
gs::Result::ValueType
T ValueType
Definition: result.h:64