I have an existing std::ostream-like type, which has several operator<< overloads for various types. Since that type is used as a const& argument to other APIs, I'm adding convenience factory-functions for easy inline use, at call sites.
I wrote the code below, which works fine (VS2019 and GCC9), but I was wondering several things:
- Do I really need the 1-arg overload? Is there benefits to having it?
- The 1-arg overload uses (Scott Meyers') magic-references, but should the variadic overload use them to? I tried
Ts...&&, but VS2019 didn't like that. - In Debug, I followed the return statements, and saw osl being move-constructed, when I was expecting Copy-Elision to take place, for such a helper, to make it zero-overhead. Is this a Debug-build artifact? Or somehow Copy-Elision cannot take place here? If so, why?
template <typename T> inline
OStreamLike bind(T&& val) {
OStreamLike osl(1);
osl << val;
return osl;
}
template <typename... Ts> inline
OStreamLike bind(Ts... vals) {
OStreamLike osl(sizeof...(Ts));
((osl << vals), ...);
return osl;
}
1rst overload isn't required.
The only benefit is the reference to avoid copy (which might be done for the variadic overload).
Forwarding-reference for variadic would use
Ts&&... argssyntax.but from the above code, you don't need forwarding references, regular const reference would be my choice
const Ts&... args.NRVO is not mandatory, even in C++17.
NRVO is applicable here, and I expect it at least in optimized build.