c++recursionpass-by-referencewrapperout-parameters

Wrapper around a function that modifies its arguments when we want to maintain caller state


Is it good practice to create a wrapper around a function that modifies its arguments (out parameters) and we want to maintain the caller state?

Is there a better way to achieve this?

The below example is a recursive function that will modify its arguments on each recursion. We pass by reference to save copies. The problem is that it will modify the caller state and this side effect must be considered by the user.

// Wrapper to return by value
// Example of caller
T1 data_1 = ...
T2 data_2 = ...

T3 result = foo(data_1, data_2);

T3 foo(T1 data_1, T2 data_2) // copy
{
    T3 result{};

    foo(data_1, data_2, result);

    return result;
}

void foo(T1 &data_1, T2 &data_2, T3 &result)
{
    // ...
    foo(data_1.modify(), data_2.modify(), result);
}

// Alternative, out parameter by reference, will modify data_1 and data_2
// Example of caller
T1 data_1 = ...
T2 data_2 = ...

T3 result{};

foo(data_1, data_2, result);



void foo(T1 &data_1, T2 &data_2, T3 &result)
{
    // ...
    foo(data_1.modify(), data_2.modify(), result);
}

Solution

  • It's fine, and not uncommon if you have code written before move semantics, especially for an older compiler which may have been weak at copy elision.

    As you say it's clearer, generally optimises well, and saves declaring local temporaries at call sites.

    If you have a type that either can't be moved or default constructed, you can still fall back on the old interface.