2013-04-06 2 views
20

나는이 GCC와 연타 실패 놀랍게도이 코드컴파일러는 "A (A & amp;)"가 잠시 동안 rvalues를 허용한다고 생각합니까?

struct A { A(); A(A&); }; 
struct B { B(const A&); }; 

void f(A); 
void f(B); 

int main() { 
    f(A()); 
} 

있습니다. 연타는 두 번째 f이 잘 작동 할 때

Compilation finished with errors: 
source.cpp:8:10: error: no matching constructor for initialization of 'A' 
     f(A()); 
     ^~~ 
source.cpp:1:21: note: candidate constructor not viable: expects an l-value for 1st argument 
    struct A { A(); A(A&); }; 
        ^
source.cpp:1:16: note: candidate constructor not viable: requires 0 arguments, but 1 was provided 
    struct A { A(); A(A&); }; 
      ^
source.cpp:4:13: note: passing argument to parameter here 
    void f(A); 

왜 그들이 첫 번째 f을 선택합니까 예를 들어 말한다? 처음으로 f을 제거하면 호출이 성공합니다. 어떻게 내가 중괄호 초기화를 사용하는 경우, 또한

int main() { 
    f({A()}); 
} 

그들은 모두 두 번째 f 전화 잘 작동, 나에게 더 이상이다.

답변

17

이것은 언어 특질입니다. A이 인수 유형 (A)과 일치하도록 변환 할 필요가 없기 때문에 첫 번째 f이 더 잘 매치되지만 컴파일러가 호출을 시도하면 적절한 복사 생성자를 찾을 수 없으므로 호출이 실패합니다. 이 언어에서는 과부하 해결 단계를 수행 할 때 실제 호출의 실행 가능성을 고려하지 않습니다.

가장 일치하는 표준 시세 ISO/IEC 14882 : 2011 13.3.3.1.2 사용자 정의 변환 시퀀스 [over.ics.user]

같은 클래스로 클래스 타입의 표현의 변환 type에 Exact Match rank가 주어지고, copy/move 생성자 (즉, 사용자 정의 변환 함수)가 실제로는 해당 유형의 기본 클래스에 대한 클래스 유형 표현식의 변환 이 변환 등급이 주어진다.) 이러한 경우에 호출됩니다. 목록 초기화 케이스

, 당신은 아마 볼 필요가 : 13.3.3.1.2 사용자 정의 변환 시퀀스 [over.ics.user]

때 비 집계 클래스의 객체 T 목록 초기화되어 입력 (8.5.4)는 오버로드 확인은 두 단계로 생성자 를 선택 :

- 처음에는 후보 함수는 클래스 T의 초기화리스트 생성자 (8.5.4)과 은 인수 목록은 노래로 이니셜 라이저 목록으로 구성됩니다. le 인수.

은 - 더 가능한 초기화리스트 생성자가 발견되지 않는 경우, 오버로드 확인은 후보 함수는 모든 클래스 T의 생성자 인수 목록 요소 이니셜 라이저 목록의 로 구성되어있는 경우, 다시 수행된다.

과부하 해상도가 f(A)f(B)에 대한 각각의 경우에 가능한 contructors보고 있기 때문에 그것은 seqence이 A()A(A&)에 있지만 B(const A&)하는 것은 여전히 ​​실행 가능 결합하려고 거부해야합니다.

+0

감사! '{...} '의 경우에는 그러한 규칙을 찾을 수 없습니다. 이것이 {{}} 사례가 왜 효과가 있는지 설명하고 있습니까? –

+0

@ JohannesSchaub-litb : 나는 잘 모르겠다. tbh, 당신은 _braced-init-list_와 함께 함수를 호출한다. 그래서 규칙은 분명히 다르다. –

+0

@ JohannesSchaub-litb [over.ics.list]를 참조하십시오. 나는 그것이 over.ics와 관련이 있다고 생각한다.ref]/3 (이전에 코드를 잘못 읽었습니다) : 실행 가능 함수의 서브 세트를 만들 때 임시 (A & A)는 임시가 아닌 좌변 치 참조에 임시 변수를 바인드하므로 실행 가능하지 않은 것으로 간주됩니다. – dyp