In C++, I have a set of variadic template functions that I'd like to accept an arbitrary number of parameters, either constant references or as r-value references (so I can move things rather than copy when possible). However, I find that the version that accepts the constant reference is called even when I'm wrapping arguments in std::move().
// Accept end of parameters.
void example () {}
// Accept a non-constant R-value reference to do a move
template <typename... More>
void example (std::string &&value, More... parameters) {
std::cout << value << ": moved" << std::endl;
example (parameters...);
}
// Accept a constant reference parameter.
template <typename... More>
void example (const std::string &value, More... parameters) {
std::cout << value << ": copied" << std::endl;
example (parameters...);
}
int main (int, char **) {
std::string first { "first" };
std::string second { "second" };
std::string third { "third" };
std::cout << "Trying variadic with move as second parameter: " << std::endl;
example (first, std::move (second), third);
// std::cout << "Trying variadic with move as first parameter: " << std::endl;
// This next line won't even compile when uncommented
// example (std::move (first), std::move (second), third);
return 0;
}
The output is:
Trying variadic with move as second parameter:
first: copied
second: copied
third: copied
instead of the expected:
Trying variadic with move as second parameter:
first: copied
second: moved
third: copied
And as a bonus, when I wrap the first argument in std::move(), I get a compile error on both g++7 and clang 9.
What am I doing wrong?