I'm currently trying to decide whether to "structify" a rather long parameter set:
void fooCopy1(std::string const& source, std::string const& destination, std::string const& filter, std::string const& temp);
to this:
struct FooCopyArgs {
std::string source;
std::string destination;
std::string filter;
std::string temp;
};
void fooCopy2(FooCopyArgs const& args);
As already answered in two other questions:
refactoring this could have several readability/maintainability advantages. For a bunch of these see the linked questions.
In general however I see one "big" problem with this approach in C++ specifically, and that is that the strings will always have to be copied before the call to this function, instead of using const& parameters.
This would be against C++ Core Guideline F.16 "pass cheaply-copied types by value and others by reference to const".
That is, non-cheap readonly parameters that would normally be passed by const ref, would need to be copied into the struct, which would be a general pessimization.
(Yes, the struct itself would be passed by const ref, but the struct data members would need to copied first.)
Example:
const string temp = ...;
const string filter = ...;
...
fooCopy2({"sourceItem", "targetItem", filter, temp});
For "sourceItem", that is a locally defined parameter value, it would not matter.
However, for the passed down args filterand temp we would have an extraneous copy that could be avoided by the plain const& approach.
Disclaimer: Obviously, in 99% of cases the performance impact won't even be observable in the final application, but still it leaves a bad taste, esp. in the context of some such "fundamental" rule as F.16.
Question : Is there any clever way around this problem, that is:
- have a safe struct as parameter type (
const& members are not safe; extremely prone to dangling references)
- avoid extraneous copy of non-cheap types
- keep composability if severeal functions use this pattern