이 ADL 예제에 대해 Bjarne이 틀렸습니까? 아니면 컴파일러 버그가 있습니까?


81

저는 The C ++ Programming Language, 4th Edition (by Bjarne Stroustrup )을 읽고 있습니다 .. 다음은 인용문입니다 (26.3.6, Overaggressive ADL) :

인수 종속 조회 (종종 ADL이라고 함)는 자세한 정보를 피하는 데 매우 유용합니다 (14.2.4). 예를 들면 :

#include <iostream>

int main()
{
    std::cout << "Hello, world" << endl; // OK because of ADL
}

인수 종속 조회가 없으면 endl조작자를 찾을 수 없습니다. 그 첫 번째 인수는 것을 컴파일러 공지이므로 <<된다 ostream정의 std. 따라서 endlin std을 찾아서 찾습니다 (in <iostream>).

다음 은 컴파일러가 생성 한 결과 입니다 (C ++ 11 모드).

prog.cpp: In function ‘int main()’:
prog.cpp:4:36: error: ‘endl’ was not declared in this scope
 std::cout << "Hello, world" << endl;
                                ^

이것은 컴파일러 또는 책의 버그입니다. 표준은 무엇을 말합니까?

최신 정보:

좀 명확히해야 겠네요. 정답은를 사용하는 것임을 알고 있습니다 std::endl. 질문은 책의 텍스트에 관한 것이 었습니다. 로 클런 이스턴은 이미 그냥 오타 아니다 말했다. 전체 단락이 (아마도) 잘못되었습니다. 이 책이 다른 (덜 알려진) 저자의 책이라면 이런 종류의 오류를 받아 들일 수 있지만, Bjarne이 저술했기 때문에 나는 여전히 의심 스럽습니다.


12
std::endl버그 없음
aaronman

3
제 경험상 책은 버그와 오타로 악명이 높습니다. 좋은 책에서 사소하거나 분명하기를 바랍니다.
Neil Kirk

31
@aaronman OP는 분명히 그것을 알고 있습니다. 인용문에서 Bjarne (C ++의 창시자)std::ADL로 인해이 경우에는 필요하지 않다고 주장하는 것으로 보입니다 . 그러나 이것은 컴파일되지 않으므로 질문입니다.
BlueRaja-Danny Pflughoeft

6
예, 요점은 책이 명백하게 잘못된 것을 말한다는 것입니다. 오타가 아닙니다. 전체 단락이 실제로 사실이 아닌 것을 설명하기 위해 작성되었습니다. 책의 버그입니다.
DanielKO 2013-08-07

7
@maverik 그것은 이다 책에 오류가. 나는 몇 분 전에이 문제를 그에게보고했으며 그의 대답에 대해 알려 드리겠습니다.
알리

답변:


83

컴파일러의 버그가 아닙니다. ADL은 인수가 아닌 함수 를 조회하는 데 사용됩니다 . 여기에서 ADL을 통해 매개 변수 와 (무엇이되어야하는지) 살펴보면서 찾은 함수 입니다.operator<<std::coutstd::endl


2
사실, 돌이켜 보면 이것은 std::endl사실 (혼란스럽게도) 함수 인 사실을 이용하여 코드를 유효하게 만드는 방법을 고무 시킵니다.endl(std::cout << "Hello, world"); // OK because of ADL
alfC

49

오타라고 말하는 사람들에게는 그렇지 않습니다. Bjarne이 실수를했거나 컴파일러가 잘못했습니다. OP가 게시 한 다음 단락은 다음과 같습니다.

인수 종속 조회가 없으면 endl 조작자를 찾을 수 없습니다. 그대로, 컴파일러는 <<에 대한 첫 번째 인수가 std에 정의 된 ostream임을 인식합니다. 따라서 std에서 endl을 찾고 (에서 <iostream>) 찾습니다 .


18
당신은 여기에서 실제로 책에서 그것을 읽은 유일한 사람인 것 같습니다. 이는 언어 규칙의 중대한 변경으로 현재 모든 C ++ 컴파일러를 비표준 (C ++ 11 용)으로 만들거나 Mr. Stroustrup의 눈부신 오류 (오타가 아닌)입니다. 개정판을 받기 위해 2 개월을 더 기다렸 으면합니다. 그는 수염을 다시 키우는 것이 좋습니다.
DanielKO 2013-08-07

그건 그렇고, 마크 업은 따옴표의 마지막 부분을 먹었습니다. 아마도 백틱 "(in <iostream>) "을 사용하고 싶을 것입니다 .
DanielKO 2013-08-07

20

다른 사람들이 이미 지적했듯이 책의 오타입니다. 그러나 책에서 의미하는 것은 우리가

std::operator<<(std::cout, "Hello, world").operator<<(std::endl);

ADL없이. 그것이 Bjarne이 장황함을 의미하는 것입니다.


나는 바로 잡았다. 로 클런 이스턴는 지적이 오타하지만 아닌 실수 책이다. 나는이 책에 접근 할 수 없어서 그 단락을 읽고 스스로 깨닫지 못했던 것이다. 나는이 실수를 Bjarne에게보고하여 그가 고칠 수 있도록했습니다.


이상한. 동일한 예가 Wikipedia에 있으며

참고이 std::endl기능이지만,이에 대한 인수로 사용되기 때문에 그것은, 전체 자격을 필요로 operator<<( std::endl함수 포인터가 아닌 함수 호출).

의심 할 여지없이 책의 실수입니다. 그럼에도 불구하고이 예제 std::operator<<(std::cout, "Hello, world").operator<<(std::endl);는 ADL이 자세한 정도를 줄이는 데 어떻게 도움이되는지 보여줍니다.


내 실수지적 해준 gx_ 에게 감사드립니다 .


그것은 오타 이상이었습니다. 그는 무언가를 생각했습니다. std::operator<< 일어나는지) 잘못된 정보로 전체 단락을 작성했습니다. ADL 규칙이 변경되었고 컴파일러가 이제 깨 졌다고 믿게 만듭니다.
DanielKO 2013-08-07

실제로 책에는 17.2.5와 같은 몇 가지 오타가있는 것 같습니다.
AndersK

@DanielKO 나는 정정 당했다; 내 대답을 수정했습니다. 감사합니다. 이 책에 대한 액세스 권한이 없기 때문에 오타라고 생각했습니다. 어쨌든 ADL은 자세한 정보를 줄이는 데 도움이되며 제가 제공 한 코드가 그 예입니다. 어쨌든 말해 주셔서 감사합니다.
알리

실제로 우리가 작성해야하는 것은 std::operator<<(std::cout, "Hello, world").operator<<(std::endl);( 비회원 참조)operator<<회원 참조operator<< )
gx_

10

힌트는 "인수 종속 조회"라는 이름에 있습니다.

이 작품 것으로, 규정되지 않은 함수 이름에 대한 조회의 따라인수 .

그것은 조회와는 아무 상관 없어 있어요 위해를 인수를.

비얀 미스 포크.


8

책은 없지만 이것은 책의 오류 인 것 같습니다. 네임 스페이스 한정자가 없다는 사실은 ADL과 아무 관련이 없습니다. 이어야합니다 std::endl.


1
나는 동의한다. 그러나 이것은 다소 이상한 진술입니다 (나는 책에있는 것을 의미합니다). 나는 Bjarne이 그것에 대해 알기를 바랍니다.
maverik

@maverik 아마도 그는 이미 그랬을 것입니다. 누군가 이미 이것을보고했다는 사실에 놀라지 않을 것입니다. 그렇지 않다면 :)
Borgleader

나는 다른 사람이 이미 발견했다 추측 것, 정말 그냥 오타 @maverik
aaronman

2
네, 정말 모든 진술을 오해 std::cout했습니다.operator<< ,하지 endl.
maverik

4

예, 오류입니다. 예제는 형식이 잘못되어 컴파일해서는 안됩니다. ADL은 함수 호출 표현식을 도입하는 정규화되지 않은 함수 이름에 적용됩니다. endl조회를 시도하는 ID 표현식 std::endl입니다. endl함수 호출 표현식을 도입하지 않으므로 인수 종속 조회가 사용되지 않고 정규화되지 않은 조회 만 사용되므로 std::endl의도 한대로 찾을 수 없습니다 .

더 간단하고 올바른 예는 다음과 같습니다.

#include <vector>

int main()
{
    std::vector<int> x, y;
    swap(x,y); // calls std::swap due to ADL
}

요약하면, f(x,y,z)정규화되지 않은 ID (예 :)를 가진 함수 호출 (예 f:)을 조회 하기 전에 먼저 함수 의 매개 변수 (예 :x,y,z :)를 분석하여 유형을 결정합니다. 연결된 네임 스페이스 목록은 형식에 따라 구성됩니다 (예 : 형식 정의의 둘러싸는 네임 스페이스는 연결된 네임 스페이스 임). 그런 다음 이러한 네임 스페이스에서 함수를 추가로 검색합니다.

Bjarne의 예의 의도는 ADL을 과시하는 것입니다. std::operator<< 기능을하지 std::endl. 이 때문에 오버로드 연산자, 사실 함수 호출 식에 있는지 추가 이해가 필요 x << y수단을 operator<<(x,y), 및 operator<<규정 화되지 않은 이름이며, 따라서 ADL은 적용됩니다. 좌변의 종류는 std::ostream매우 std연관된 공간이므로 std::operator<<(ostream&, ...)발견된다.

수정 된 설명은 다음과 같아야합니다.

인수 종속 조회가 없으면 네임 스페이스 <<에서 오버로드 된 연산자를 std찾을 수 없습니다. 그대로 컴파일러는 <<에 대한 첫 번째 인수가 std에 정의 된 ostream임을 인식합니다. 따라서 <<std 에서 연산자 를 찾고 (에서 <iostream>) 찾습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.