template<
typename T>
class rclcpp::ResultOf< T >
The result of a fallible operation: Result when it produces nothing, ResultOf<T> when it produces a value. This is the whole error channel — RFC-0018 forbids exceptions, so nothing here throws, and RFC-0089 §"The error channel, settled" is the rule for which one an API picks. Use the RCLCPP_TRY macro for early return on error.
ONE TEMPLATE, TWO SPELLINGS — and the second spelling is forced by the language rather than chosen. RFC-0089 asks for one template named Result, the value-less case as Result<void>, and Result as its alias. C++ cannot express that: an identifier in a scope is a class, a class template, or an alias, never two of those. Measured on gcc 12.3 and clang 14, every route is ill-formed —
template <typename T = void> class Result; Result f();
"invalid use of template-name 'Result' without an argument list"
under -std=c++14, and "deduced class type 'Result' in function
return type" under -std=c++17, where CTAD gets close enough to
change the message and no closer.
template <typename T> class Result; class Result { };
"class template 'Result' redeclared as non-template"
template <typename T> class Result; using Result = Result<void>;
"redeclared as different kind of entity"
So the STRUCTURE the RFC asks for is here in full — one template, the value-less case IS its void specialization, Result is an alias for that specialization, and there are no longer two unrelated types to learn. Only the template's own spelling differs, because Result is what 1100+ call sites and the entire public API already write for the void case, and a bare name is the one worth keeping bare. phase-427 W8.
The primary template is DECLARED here and defined below Result, because the value-less specialization is what ResultOf<T>::error(const Result&) names. NROS_NODISCARD sits on the two DEFINITIONS and not on this declaration: repeating it would be legal and redundant, and a reader looking at a class body should be able to see whether its result may be dropped.
ResultOf<T> — a fallible operation that produces a value (phase 123.B.4; this was Expected<T> until phase-427 W8 folded both halves of the error channel into one template).
Lets factory functions return constructed entities by value instead of forcing the out-param + Result idiom. Trade-off: requires T to be default-constructible and move-constructible (Node, Publisher, Subscription all satisfy both today). Storage is direct (the value lives inline, no allocation) — when the result holds an error the value member is default-constructed and idle.
Usage:
auto node_r = rclcpp::Node::make(
"my_node");
Definition client.hpp:129
Out-param create_node(node, "name") remains the canonical zero-cost API for embedded / strictly-no-alloc code; make() is a hosted-friendly convenience that closes the rclcpp / rclrs idiom gap.