C++ Mapping for Parameters and Return Values
In Parameters
An in parameter is mapped to a C++ parameter with the same name.
The type of the mapped C++ parameter depends on the Slice type and on the direction of the parameter: are you giving this parameter to Ice for marshaling (an outgoing value), or is Ice giving you this parameter after unmarshaling it (an incoming value)?
For incoming values, the mapped C++ type is always “by value”: Ice transfers these arguments to you, and you get full ownership. For outgoing values, Ice only needs to “borrow” the arguments while it marshals them synchronously into the payload of the request.
Slice Parameter Type | Mapped C++ Parameter Type (Outgoing) | Mapped C++ Parameter Type (Incoming) Always by value |
---|---|---|
| By value
|
|
| “view”
|
|
| Const reference
|
|
| Const reference of shared pointer
|
|
| Const reference of optional
|
|
Out Parameters in Synchronous Functions
A Slice parameter is mapped to a parameter with the same name in synchronous proxy and skeleton functions. The type of the mapped C++ parameter is a non-const reference.
Consider the following example:
struct NumberAndString
{
int x;
string str;
}
sequence<string> StringSeq;
dictionary<long, StringSeq> StringTable;
interface ServerToClient
{
void op1(out int i, out float f, out bool b, out string s);
void op2(out NumberAndString ns, out StringSeq ss, out StringTable st);
void op3(out ServerToClient* proxy);
}
The Slice compiler generates a proxy class for this definition (we omit the async overloads):
class ServerToClientPrx : public Ice::Proxy<ServerToClientPrx, Ice::ObjectPrx>
{
public:
void op1(int& i, float& f, bool& b, std::string& s, const Ice::Context& = Ice::noExplicitContext);
void op2(NumberAndString& ns, StringSeq& ss, StringTable& st, const Ice::Context& = Ice::noExplicitContext);
void op3(std::optional<ServerToClientPrx>& proxy, const Ice::Context& = Ice::noExplicitContext);
};
Return Values in Synchronous Functions
A Slice return value is mapped to a C++ return value in synchronous proxy and skeleton functions. The C++ type is naturally returned “by value”.
Out Parameters and Return Values in Asynchronous Functions
Future-Returning Proxy Functions
One of the two overloaded proxy member functions <operation-name>Async
returns a std::future<T>
.
When the Slice operation returns something – either through a return value or one or more out parameters – the future holds the return value and/or out parameters, in order of declaration (the return value, if any, is first). If there is a single return value or out parameter, the future holds the mapped C++ type. Otherwise, the future holds a std::tuple
.
These parameters are all mapped “by value”, like in the Incoming column of In Parameters, since you’re receiving these values from Ice.
Callback Proxy Functions
The other overloaded proxy member functions <operation-name>Async
accepts a response callback function that consumes the return value and out parameters (if any). This callback function is provided by you (the application), and is called by Ice.
These parameters are all mapped “by value”, like in the Incoming column of In Parameters, since you’re receiving these values from Ice.
When the operation has a return value and one ore more out parameters, the return value is mapped to a parameter named returnValue
int the C++ response callback.
AMD Skeleton Functions
On the server-side, when you use AMD, the pure virtual function <operation-name>Async
on the generated skeleton class provides a response callback that accepts the return value and out parameters (if any). This callback function is provided by Ice, and you (the application) call this function in your implementation of <operation-name>Async
.
The return value and out parameters are all mapped like in the Outgoing column of In Parameters, since you’re loaning these values to Ice for marshaling.
Optional Parameters
The mapping for optional parameters is the same as for required parameters, except each mapped C++ type is enclosed in a std::optional
.
Consider the following operation:
optional(1) int execute(optional(2) string params, out optional(3) float value);
The corresponding C++ proxy function is:
// Synchronous variant
std::optional<std::int32_t> execute(std::optional<std::string_view> params, std::optional<float>& value, ...);
and the corresponding C++ skeleton function is:
// Synchronous variant
virtual std::optional<std::int32_t> execute(std::optional<std::string> params, std::optional<float>& value, ...);
An optional parameter with a proxy type is mapped to a std::optional<InterfaceNamePrx>
, and not to a std::optional<std::optional<InterfaceNamePrx>>
. This is the same rule as for optional fields with proxy types.