I am working on an implementation of EDDSA digital signatures and as the values used in the calculations can be up to 521 bits in size (scalers) and points have three scalers (projective coordinates), passing values by copy are expensive in terms of stack space and argument copy. To eliminate as many copies as possible, I pass the arguments as 'const &', create a local variable, perform the computation and place the result in the local variable, and then return the local variable. Note: Code is C++17 (clang).
struct Point { /* ... */ } ;
friend Point operator + (Point const & lhs , Point const & rhs)
{
Point res ;
/* Do addition and place result into 'res' */
return res ;
}
This works fine for all possible argument types (& , const & , &&) but always requires additional stack space for the result. If a temporary is passed (Point &&), it can be used to hold the result and save stack space. The question here is how to correctly return the result?
friend Point operator + (Point && lhs , Point const & rhs)
{
/* Do addition and place result into 'lhs' */
return lhs ; // Not sure what is exactly returned here : Danger of dangling reference or ok?
}
/* OR */
friend Point && operator + (Point && lhs , Point const & rhs)
{
/* Do addition and place result into 'lhs' */
return std::move (lhs) ; // Danger of dangling reference to caller if not used correctly
}
I understand that the second case (return Point &&) can lead to a dangling reference if not handled correctly by the caller.
I have read similar questions and answers on returning && values, but I did not find anything specific to returning a && argument as a value (first case above).
How exactly does C++ define the return value behavior for the first case (return Point when the argument was Point &&)?
Is there a better (ie: efficient and safe) method for eliminating copies and reusing temporary argument memory?
Additionaly, if the overloaded operator is declared as a template, I understand the '&&' argument is treated differently to support perfect forwarding.
template <class Point> friend Point operator + (Point && lhs , Point const & rhs)
{
/* Do addition and place result into 'lhs' */
return lhs ;
}
How exactly does the '&& argument get treated differently (if so) than in the non-template definition and what is the correct way to return the result?