0

rvalues ​​및 lvalue 참조를 허용하는 가변 템플릿 함수를 작성하고 싶습니다. 그것은 std :: strings을 대문자로하고 대문자가 된 후에 각 매개 변수를 표시합니다. 함수가 끝나면 모든 lvalues는 대문자를 유지해야합니다 (예 : lvalues가 참조로 전달됨).rvalue 및 lvalue 참조를 모두 허용하는 가변 템플릿?

내가 컴파일하는 코드 작업이 위의 덩어리를 얻을 수있는 방법
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" 

을 같이 예를 들면 다음과 같습니다
, 나는이 문제를 하시겠습니까?

지금까지 정보를 출력 할 수 있었지만 두 가지 값 유형의 대소 문자를 처리하는 방법을 알지 못했습니다. 다음 코드 이 컴파일됩니다. 작동하지 않는 행을 주석 처리했기 때문입니다.

#include <string> 
#include <iostream> 
#include <algorithm> 

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, const Strings&... rest) { 
    //std::transform(str.begin(), str.end(), str.begin(), ::toupper); <- will not compile 
    std::cout << str << " "; 
    Capitalize_And_Output(rest...); 
    return; 
} 

int main() { 

    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 keep changed value 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" 

    return 0; 
} 

어떻게 작동합니까?
아마도 rvalues가 다른 유형이기 때문에 변환 함수가 작동하지 않을 수 있습니까? 그들은 char * s입니까?

내 머리를 통과하는 것 :
형질을 가지고 뭔가해야합니까?
R 값이있는 항목이 있습니까?
보편적 인 경의를 가진 무언가 (은 실제로이 아닙니다.)

용어의 오용을 수정하십시오!

답변

1

첫째, 프로그램이 작동하지 않는 근본적인 이유는 rvalue/lvalue 호환성과 관련이있을뿐만 아닙니다. 이 값을 인수로 전달하는 버전을 고려하십시오.

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

이 경우 주 코드가 작동하지 않습니다. 그 다음

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

라인

Capitalize_And_Output("hello",planet,earth); 
을 고려 표시하려면 컴파일러는 첫 번째 인수의 "CONST 문자"를 고려하기 때문에

가 작동하지 않습니다 (숯불 .begin이없는()와 .END() iterators!)!). 사실, 난 지금 다시 원래의 좌변 /를 rvalue 질문에 g++

instantiated from here 
teste.cpp:14:5: error: request for member ‘begin’ in ‘str’, which is of non-class type ‘const char*’ 

에서 다음과 같은 오류 메시지가 (무너 규칙은 & & & = &가. 여기에 해결책이 말했다. 또한이 "완벽한을 잊을 수 없어 rvalue 참조를 전달하십시오.확실하지 않은이 처리하는 방법 :

그런 다음 최종 답변을 요약

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 

편집해야한다는 사실이다 문제는 the standard에 설명되어 있습니다.

+0

나는 char */std :: string 부분을 이해하지만이 방법이 효과가 없다고 생각합니다. 이제 (&, &) 및 (&&, &&) 함수 사이에 모호한 오류가 발생했습니다. –

+0

죄송합니다 .. 과부화가 필요하지 않습니다. 규칙이 무너지기 때문에 과부하가 걸리지 않습니다. 이제 작동합니다 (테스트 해 보았습니다). 문제는 모든 가능한 옵션을 명시 적으로 오버로드하지 않고 표준에서 문제를 처리하는 방법을 모르겠다는 것입니다. –

+1

FWIW이 경우 두 개의 과부하를 사용하지 않아도됩니다. http://ideone.com/cPGw07 – Simple

관련 문제