-
Notifications
You must be signed in to change notification settings - Fork 82
Function parameters
In-Parameters (those that come with a value that may not be modified) shall be passed as type const &
except if they are POD, in which case you may use type const
.
If you need to copy an in-parameter inside your function, instead do this in the parameter construction so you don't needlessly copy temporaries:
This always involves a copy:
void foo(my_type const & in)
{
my_type my_copy{in};
my_copy.foo = 7;
// ...
}
This otoh might use the move-constructor of T to prevent a copy:
void foo(my_type in)
{
in.foo = 3;
// ...
}
In-Out-Parameters (those that come with a value which will be modified) shall be passed as T &
.
This is a big difference to SeqAn2!
SeqAn2:
void foobar(type1 & out1, type2 & out2, type3 & in_out, type4 const & in, tag_type const & /**/)
{
// ...
}
// ...
type1 out;
type2 out2;
foobar(out, out2, ...);
SeqAn3:
auto foobar(type3 & in_out, type4 const & in, tag_type const & /**/)
{
type1 out1;
type2 out2;
// ...
return { out1, out2 };
}
// ...
type1 out;
type2 out2;
std::tie(out, out2) = foobar( ...); // move assignment
// ... OR via structured bindings:
auto [out, out2] = foobar( ...); // (N)RVO
This is now possible because we have "named return value optimization" (NRVO) or "guaranteed copy elision" of return values with C++17.
If you need to keep the return type generic, or need to specialize over the return type, instead use the "old style" where the out parameter is treated as an in-out parameter.
This example illustrates where this makes more sense:
// this would be via return values
template <alphabet_concept out_type, alphabet_concept in_type>
out_type convert(in_type const & in, out_type const & /*tag*/)
{
// ...
return out_type{/* ... */};
}
// here the it is obviously much more intuitive to do the following:
template <alphabet_concept out_type, alphabet_concept in_type>
void convert(out_type & out, in_type const & in)
{
// ...
}
The parameter order in function definitions should normally be
- in-out
- in
- in (tags and pure type parameters)
e.g.
auto foobar(type3 & in_out, type4 const & in, tag_type const & /**/)
In cases where the above exception for out-parameters holds, these precede the in-out parameters (same as in SeqAn2).
In case where functions have parallelized and non-parallelized versions that we want to be selectable, we offer an execution policy parameter as the first parameter. This is in line with the STL and makes sense, because it allows easily forwarding the remaining parameters.