C++11 同时接受右值和左值引用的可变模板?

C++11 同时接受右值和左值引用的可变模板?,c++11,variadic-templates,rvalue-reference,typetraits,lvalue,C++11,Variadic Templates,Rvalue Reference,Typetraits,Lvalue,我想写一个可变模板函数,它接受右值和左值引用。它将std::strings大写,并在大写后显示每个参数。函数结束后,所有左值应保持大写(即通过引用传递左值)。 例如,我希望这种行为: std::string hello = "hello"; std::string planet = "planet"; std::string earth = "earth"; //the order and amount of rvalues and lvalue references, should not

我想写一个可变模板函数,它接受右值和左值引用。它将std::strings大写,并在大写后显示每个参数。函数结束后,所有左值应保持大写(即通过引用传递左值)。
例如,我希望这种行为:

std::string hello = "hello";
std::string planet = "planet";
std::string earth = "earth";

//the order and amount of rvalues and lvalue references, should not matter
Capitalize_And_Output("hello","planet","earth"); //outputs: "HELLO PLANET EARTH"
Capitalize_And_Output(hello,"planet","earth");   //outputs: "HELLO PLANET EARTH"
Capitalize_And_Output("hello",planet,"earth");   //outputs: "HELLO PLANET EARTH"
Capitalize_And_Output("hello","planet",earth);   //outputs: "HELLO PLANET EARTH"
Capitalize_And_Output(hello,planet,"earth");     //outputs: "HELLO PLANET EARTH"
Capitalize_And_Output(hello,"planet",earth);     //outputs: "HELLO PLANET EARTH"
Capitalize_And_Output("hello",planet,earth);     //outputs: "HELLO PLANET EARTH"
Capitalize_And_Output(hello,planet,earth);       //outputs: "HELLO PLANET EARTH"

//lvalue references remain changed after the function call
std::cout << hello << std::endl;  //outputs: "HELLO"
std::cout << planet << std::endl; //outputs: "PLANET"
std::cout << earth << std::endl;  //outputs: "WORLD"
std::string hello=“hello”;
std::string planet=“planet”;
std::string earth=“earth”;
//右值和左值引用的顺序和数量应该无关紧要
资本化_和_输出(“你好”、“行星”、“地球”)//输出:“你好,地球”
资本化_和_输出(你好,“行星”,“地球”)//输出:“你好,地球”
资本化_和_输出(“你好”,行星,“地球”)//输出:“你好,地球”
资本化_和_输出(“你好”,“行星”,地球)//输出:“你好,地球”
资本化_和_输出(你好,行星,“地球”)//输出:“你好,地球”
资本化_和_输出(你好,“行星”,地球)//输出:“你好,地球”
资本化_和_输出(“你好,行星,地球”)//输出:“你好,地球”
资本化_和_输出(你好,行星,地球)//输出:“你好,地球”
//在函数调用之后,左值引用保持更改
标准::cout


阅读通用参考资料。这是一种更好的思考这些事情的方式,我觉得他的视频很好地解释了右值引用

首先,程序无法运行的根本原因不仅与右值/左值兼容性有关。显示只考虑通过值

传递参数的版本
#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;
}
线路

Capitalize_And_Output("hello",planet,earth);

不起作用,因为编译器考虑第一个参数“conchar”(char没有.No.()和.Enter()迭代器!!!事实上,我在

g++

instantiated from here
teste.cpp:14:5: error: request for member ‘begin’ in ‘str’, which is of non-class type ‘const char*’
现在回到您原来的左值/右值问题(折叠规则表示&&&&=&)。这是解决方案。您也不能忘记“完美转发”右值引用

然后,对最终答案进行总结

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;
}

编辑:不确定如何处理中描述的此问题。

我理解char*/std::string部分,但我认为这不起作用。我现在发现(&,&)和(&&,&&&)函数之间存在模糊错误。抱歉..您不需要重载..它可以在没有重载的情况下工作,因为规则正在崩溃。现在它可以工作了(我测试了它)。问题是,我不确定如何在没有显式重载所有可能选项的情况下处理标准中的问题。FWIW在这种情况下,您可以避免使用两个重载:
instantiated from here
teste.cpp:14:5: error: request for member ‘begin’ in ‘str’, which is of non-class type ‘const char*’
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;
}
    Capitalize_And_Output(std::string("hello"),planet,earth);  // this will work