I encounter the pass by value and move idiom quite often:
struct Test
{
Test(std::string str_) : str{std::move(str_)} {}
std::string str;
};
But it seems to me that passing by either const reference or rvalue reference can save a copy in some situations. Something like:
struct Test1
{
Test1(std::string&& str_) : str{std::move(str_)} {}
Test1(std::string const& str_) : str{str_} {}
std::string str;
};
Or maybe using a forwarding reference to avoid writing both constructors. Something like:
struct Test2
{
template<typename T> Test2(T&& str_) : str{std::forward<T>(str_)} {}
std::string str;
};
Is this the case? And if so, why is it not used instead?
Additionally, it looks like C++20 allows the use of auto parameters to simplify the syntax. I am not sure what the syntax would be in this case. Consider:
struct Test3
{
Test3(auto&& str_) : str{std::forward<decltype(str_)>(str_)} {}
std::string str;
};
struct Test4
{
Test4(auto str_) : str{std::forward<decltype(str_)>(str_)} {}
std::string str;
};
Edit:
The suggested questions are informative, but they do not mention the "auto" case.
Indeed, but it requires more overloads (and even worst with several parameters).
Pass by value and move idiom has (at worst) one extra move. which is a good trade-off most of the time.
Forwarding reference has its own pitfalls:
{..}syntax for parameter as{..}has no type. would not be possible.requiresor SFINAE). would produces error inside the constructor, and not at call site (so error message less clear, and SFINAE not possible).std::stringcannot be constructed fromTest2&.