nros C++ API
Lightweight ROS 2 client for embedded real-time systems (C++ headers)
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1// nros-cpp: Result type for error handling
2// Freestanding C++ — no exceptions, no STL required
3
12#ifndef NROS_CPP_RESULT_HPP
13#define NROS_CPP_RESULT_HPP
14
15#include <cstdint>
16#include <utility>
17#if defined(NROS_CPP_STD) || (__STDC_HOSTED__ + 0)
18#include <cstdio>
19#endif
20
21namespace nros {
22
30enum class ErrorCode : int32_t {
32 Ok = 0,
34 Error = -1,
36 Timeout = -2,
38 InvalidArgument = -3,
40 NotFound = -4,
42 AlreadyExists = -5,
44 Full = -6,
47 NotInitialized = -7,
49 BadSequence = -8,
51 ServiceFailed = -9,
53 PublishFailed = -10,
57 NotAllowed = -12,
62 Rejected = -13,
64 TryAgain = -14,
66 Reentrant = -15,
68 Unsupported = -16,
70 TransportError = -100,
71};
72
73// Issue #229 pin (self-consistency half): the values above ARE the shared
74// numbering. The cross-space asserts against the real C constants live in
75// parameter.hpp (vs NROS_RET_*) and node.hpp (vs NROS_CPP_RET_*), where
76// those headers are visible.
77static_assert(static_cast<int32_t>(ErrorCode::NotFound) == -4 &&
78 static_cast<int32_t>(ErrorCode::AlreadyExists) == -5 &&
79 static_cast<int32_t>(ErrorCode::Full) == -6 &&
80 static_cast<int32_t>(ErrorCode::NotInitialized) == -7 &&
81 static_cast<int32_t>(ErrorCode::TryAgain) == -14 &&
82 static_cast<int32_t>(ErrorCode::Reentrant) == -15 &&
83 static_cast<int32_t>(ErrorCode::Unsupported) == -16,
84 "ErrorCode numbering must match nros_ret_t (issue #229)");
85
90class Result {
91 public:
93 constexpr Result() : code_(ErrorCode::Ok) {}
95 constexpr Result(ErrorCode code) : code_(code) {}
97 constexpr Result(int32_t raw) : code_(static_cast<ErrorCode>(raw)) {}
98
100 bool ok() const { return code_ == ErrorCode::Ok; }
101
103 explicit operator bool() const { return ok(); }
104
106 ErrorCode code() const { return code_; }
107
109 int32_t raw() const { return static_cast<int32_t>(code_); }
110
112 static constexpr Result success() { return Result(ErrorCode::Ok); }
113
114 private:
115 ErrorCode code_;
116};
117
128#define NROS_TRY(expr) \
129 do { \
130 ::nros::Result _nros_r = (expr); \
131 if (!_nros_r.ok()) return _nros_r; \
132 } while (0)
133
147#ifndef NROS_TRY_LOG
148#if defined(NROS_CPP_STD) || (__STDC_HOSTED__ + 0)
149#define NROS_TRY_LOG(file, line, expr, ret) \
150 ::std::fprintf(stderr, "[nros] %s:%d %s -> %d\n", (file), (line), (expr), (int)(ret))
151#else
152#define NROS_TRY_LOG(file, line, expr, ret) ((void)(file), (void)(line), (void)(expr), (void)(ret))
153#endif
154#endif
155
156#define NROS_TRY_RET(expr, retval) \
157 do { \
158 ::nros::Result _nros_r = (expr); \
159 if (!_nros_r.ok()) { \
160 NROS_TRY_LOG(__FILE__, __LINE__, #expr, _nros_r.raw()); \
161 return (retval); \
162 } \
163 } while (0)
164
168#define NROS_CHECK(expr) \
169 do { \
170 ::nros::Result _nros_r = (expr); \
171 if (!_nros_r.ok()) { \
172 NROS_TRY_LOG(__FILE__, __LINE__, #expr, _nros_r.raw()); \
173 return; \
174 } \
175 } while (0)
176
198template <typename T> class Expected {
199 public:
200 static Expected ok(T value) {
201 Expected e;
202 e.ok_ = true;
203 e.value_ = ::std::move(value);
204 return e;
205 }
206 static Expected error(ErrorCode code) {
207 Expected e;
208 e.ok_ = false;
209 e.error_ = code;
210 return e;
211 }
212 static Expected error(const Result& r) { return error(r.code()); }
213
214 bool ok() const { return ok_; }
215 explicit operator bool() const { return ok_; }
216
217 T& value() & { return value_; }
218 const T& value() const& { return value_; }
219 T&& value() && { return ::std::move(value_); }
220
221 ErrorCode error() const { return error_; }
222 Result error_as_result() const { return Result(error_); }
223
224 private:
225 Expected() : ok_(false), error_(ErrorCode::Error), value_() {}
226
227 bool ok_;
228 ErrorCode error_;
229 T value_;
230};
231
232} // namespace nros
233
234#endif // NROS_CPP_RESULT_HPP
Definition result.hpp:198
Result error_as_result() const
Definition result.hpp:222
T & value() &
Definition result.hpp:217
const T & value() const &
Definition result.hpp:218
static Expected error(ErrorCode code)
Definition result.hpp:206
static Expected error(const Result &r)
Definition result.hpp:212
static Expected ok(T value)
Definition result.hpp:200
ErrorCode error() const
Definition result.hpp:221
T && value() &&
Definition result.hpp:219
bool ok() const
Definition result.hpp:214
Definition result.hpp:90
static constexpr Result success()
Named constructors.
Definition result.hpp:112
int32_t raw() const
Get the raw integer code (for FFI interop).
Definition result.hpp:109
ErrorCode code() const
Get the underlying error code.
Definition result.hpp:106
constexpr Result(ErrorCode code)
Construct from a typed code.
Definition result.hpp:95
constexpr Result(int32_t raw)
Construct from a raw FFI return value (int32_t).
Definition result.hpp:97
bool ok() const
Returns true if the operation succeeded.
Definition result.hpp:100
constexpr Result()
Default-construct a success.
Definition result.hpp:93
Definition nros.hpp:55
ErrorCode
Definition result.hpp:30
@ InvalidArgument
Null pointer, empty topic name, or out-of-range value.
@ NotFound
Entity not found (topic, parameter, service…).
@ Reentrant
A blocking call was made from inside a callback.
@ PublishFailed
Publish failed.
@ BadSequence
Operation invalid in the current state (bad call sequence).
@ ServiceFailed
Service request/reply failed.
@ AlreadyExists
Already exists (duplicate declare/register).
@ Error
Generic failure not covered by a more specific code.
@ TransportError
Underlying zenoh-pico / DDS transport rejected the operation.
@ Unsupported
Operation not implemented by the active backend.
@ Full
Static pool exhausted (executor slots, subscription buffers, …).
@ Timeout
Operation deadline elapsed before completion.
@ SubscriptionFailed
Subscription create/take failed.
@ TryAgain
Transient — no data ready yet (non-blocking take). Retry later.
@ NotAllowed
Operation not allowed for this entity/backend.