First, the underlying reason why your program is not working is not only related to rvalue/lvalue compatibility. To show that consider this version that only pass the arguments by value
#include <string>
#include <iostream>
#include <algorithm>
template<typename T>
void Capitalize_And_Output(T str) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
std::cout << str<< std::endl;
return;
}
template<typename First, typename ... Strings>
void Capitalize_And_Output(First str, Strings... rest) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
std::cout << str << " ";
Capitalize_And_Output(rest...);
return;
}
In this case your main code will not work either. To show that consider the following
int main() {
std::string hello = "hello";
std::string planet = "planet";
std::string earth = "earth";
Capitalize_And_Output(std::string("hello"),planet,earth); // this will work
//Capitalize_And_Output("hello",planet,earth); // original code -> this will NOT work
return 0;
}
The line
Capitalize_And_Output("hello",planet,earth);
does not work because compiler consider the first argument "a const char" (char does not have .begin() and .end() iterators!)!. In fact, I get the following error message in g++
instantiated from here
teste.cpp:14:5: error: request for member ‘begin’ in ‘str’, which is of non-class type ‘const char*’
Now back to your original lvalue/rvalue question (collapsing rule says that && & = &. Here is the solution. You also cannot forget to "perfect forward" the rvalue references.
Then, a summary of the final answer is
template<typename T>
void Capitalize_And_Output(T&& str) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper); // <- will not compile
std::cout << str<< std::endl;
return;
}
template<typename First, typename ... Strings>
void Capitalize_And_Output(First&& str, Strings&&... rest) {
std::transform(str.begin(), str.end(), str.begin(), ::toupper); //<- will not compile
std::cout << str << " ";
Capitalize_And_Output(std::forward<Strings>(rest)...); // don't forget perfect forwarding.
return;
}
plus the fact that in main you must explicit use std::string constructor
Capitalize_And_Output(std::string("hello"),planet,earth); // this will work
EDIT: not sure how to handle this problem described in the standard.