2017-03-12 6 views
3

내가 새로운 C++ 의미를 배우고 ambigious 내가이 프로그램에 오류 가지고 :전화는

#include <iostream> 
#include <string> 
#include <utility> 

std::string foo(std::string str) 
{ 
    return str + " call from normal"; 
} 

std::string foo(const std::string& str) 
{ 
    return str + " call from normal"; 
} 

std::string foo(std::string&& str) 
{ 
    return str + " call from ref ref"; 
} 

int main() 
{ 
    std::string str = "Hello World!"; 
    std::string res = foo(str); 
    std::string&& res_ref = foo(std::move(str)); 
    std::cout << "Res ref = " << res_ref << std::endl; 
    std::cout << "Str = " << str << std::endl; 
    return 0; 
} 

오류는 다음과 같습니다

:23:30: error: call of overloaded ‘foo(std::__cxx11::string&)’ is ambiguous 
    std::string res = foo(str); 

왜 모호 전화입니다 ?

+2

당신은 3 개의'foo' 함수를 가지고 있으며, 어느 것을 사용할 지 알 수 없습니다. – Carcigenicate

+0

하지만 이중 참조, 표준 함수 및 const ref, 왜 그런 문제가 발생합니까? 내가 처음 함수 선언문을 모두 잘 작동한다고 말하면, 나의 질문은 : 왜 컴파일러는 하나의 선택을 사용할 수 없습니까? – Asmozan

+1

컴파일러는'std :: string foo (std :: string str)'또는'std :: string foo (const std :: string & str)'호출 여부를 어떻게 알 수 있습니까? 당신은 정확히 같은 방법으로 그들을 호출 – UnholySheep

답변

5

보유 기간 :

std::string res = foo(str); 

두 가지 가능한 후보가 있습니다

여러 후보를 부여 할 때 선택하는 기능을 결정하는 많은, 많은 단계가 있습니다
foo(std::string);   // #1 
foo(std::string const&); // #2 

. 그러나이 경우 두 선택 모두 완전히 구별 할 수 없습니다. 인수에 대해 stringstring const& 사이의 과부하 해결을 선호하지 않습니다. 마찬가지로 rvalue 인수에는 stringstring&& 사이의 기본 설정이 없으므로 두 번째 호출도 모호한 것으로 간주됩니다.

일반적으로 어떤 기능을 선호하는 규칙은 특정과 관련이 있습니다. 예를 들어, string&을 취하는 함수와 string const&을 취하는 함수가 주어지면, 전자는 에 대한 비 const 왼쪽 값 참조로만 호출 될 수 있지만 후자는 전체 묶음으로 호출 될 수 있으므로 둘 다 실행 가능할 경우 전자는 실행 가능합니다. (특히, [over.ics.rank]/3.2.6으로 인해). 하지만이 경우에는 #1으로 전화 할 수있는 모든 것이 있으며 #2으로 전화 할 수 있습니다. #2으로 전화 할 수있는 모든 것, #1으로 전화 할 수 있습니다. 따라서 다른 것을 선호하는 이유가 없습니다.

당신은 단순히 당신이 떠나고, 그 과부하를 제거해야합니다 : 좌변에 대한

foo(std::string const&); // #2 
foo(std::string&&);  // #3 

std::string들 만 2 실용적이다. 값이 std::string 인 경우 두 가지 모두 실행 가능하지만 3 번을 선호합니다 (일반적인 지침에 따르면보다 구체적인 - 특히 [over.ics.rank]/3.2.3).

+0

참조로 어설 션을 백업하십시오. –

+1

@NickWestgate Skeptics.SE가 아닙니다. 특히 귀하의 유효성에 대해 질문하는 진술이 있습니까? – Barry

+0

@NickWestgate : 나는 아이러니를 고맙게 생각합니다.;]] – ildjarn

-2

명확성을 위해 rvalue reference (문자열 & &)를 잊어 버리고 컴파일러 인 것처럼 가장합니다.

정의 된 두 가지 기능이 있습니다

  1. foo는 (표준 : : 문자열 STR)는
  2. foo는

    감안할 때 STR이 표준은

(const를 표준 : : 문자열 & STR) :: 전화를 걸 수있는 문자열 :

foo(str); 

어떤 기능을 사용 하시겠습니까? 1 또는 2?

  1. str을 foo1에 전달할 수 있습니다.
  2. 당신은 당신도 할 수있는이 경우 2.

을 foo는하기 (포인터와 같은) STR에 const를 참조를 전달 할 수 있으므로 컴파일러는 결정할 수 없습니다.

컴파일러는 어떻게 결정합니까? 후보 함수 목록 작성, 인수에 대해 수행 할 수있는 유형 승격 또는 변환의 종류 및 필수 인수를 작성하는 데 사용할 수있는 구성자에 대한 규칙이 있습니다. Here is a simple overview 코스에서.

+0

"둘 중 하나를 할 수 있습니다"라는 것은 단지 둘 다 실행 가능하다는 것을 의미합니다 - 모호하다고 말하는 것만으로는 충분하지 않습니다. # 1이'foo (std :: string &)'이라도 할 수 있지만 그 경우는 모호하지 않습니다. – Barry

+0

downvote에 대한 의견을 보내 주셔서 감사합니다. 저는 학습자가 간단하게 유지하려고 노력하고 있었으며보다 상세한 답변에 대한 링크를 제공했습니다. –

+1

문제는 당신이 그것을 단순화했다는 것입니다. 당신의 대답은 두 명의 유력한 후보자가있을 때마다 전화가 모호하다는 것입니다. 그건 사실이 아니야. – Barry

-2

모호성이 두 기능 사이 : 당신이 함수 이름을 읽을

std::string foo(std::string str); // 1 
std::string foo(const std::string& str); // 2 

방법은 오른쪽에서 왼쪽입니다. 이러한 기능의 영어 등가물은 다음과 같습니다

  1. foostd::string 매개 변수를 사용하고 std::string을 반환하는 함수입니다.
  2. fooreferenceconstant std::string 매개 변수로 사용하고 std::string을 반환하는 함수입니다.

.

두 함수의 서명 사이에 컴파일러에서 알려진 유일한 차이점은 str의 복사본을 매개 변수로 사용할지 아니면 str에 대한 불변 참조인지 여부입니다. 컴파일러의 관점에서 볼 때,이 두 함수는 런타임 중에 우선 순위를 가지기에 충분하지 않습니다.

일반적으로 기본 유형 (int, char, short 등)이 아닌 경우 유형 자체 대신 참조를 사용하십시오. 모든 의도와 목적을 위해 std::stringstd::vector<char>과 유사하므로 문자열의 길이에 관계없이 참조로 전달하면 항상 sizeof(pointer) 데이터 트랜잭션이 발생합니다.

+1

아무도 친절하게 (내가 downvote 때문에) 내가 어디에서 배웠는지 알 수 없습니까 :) – gamiseta