“인수 종속 조회”(일명 ADL 또는“Koenig 조회”) 란 무엇입니까? 대한 좋은

인수 종속 조회가 무엇인지에 대한 좋은 설명은 무엇입니까? 많은 사람들이이를 Koenig Lookup이라고도합니다.

바람직하게는 알고 싶습니다.

  • 왜 좋은가요?
  • 왜 나쁜 일입니까?
  • 어떻게 작동합니까?


답변

Koenig Lookup 또는 Argument Dependent Lookup 은 C ++에서 컴파일러가 규정되지 않은 이름을 찾는 방법을 설명합니다.

C ++ 11 표준 § 3.4.2 / 1 상태는 다음과 같습니다.

함수 호출 (5.2.2)의 접미사 표현식이 규정되지 않은 ID 인 경우, 정규 규정되지 않은 검색 (3.4.1) 중에 고려되지 않은 다른 네임 스페이스가 검색 될 수 있으며, 이러한 네임 스페이스에서 네임 스페이스 범위 친구 함수 선언 ( 11.3) 그렇지 않으면 보이지 않을 수 있습니다. 검색에 대한 이러한 수정은 인수 유형 (및 템플리트 템플리트 인수의 경우 템플리트 인수의 네임 스페이스)에 따라 다릅니다.

간단한 용어로 Nicolai Josuttis는 1을 말합니다 .

함수의 네임 스페이스에 하나 이상의 인수 유형이 정의 된 경우 함수의 네임 스페이스를 규정 할 필요가 없습니다.

간단한 코드 예제 :

namespace MyNamespace
{
    class MyClass {};
    void doSomething(MyClass);
}

MyNamespace::MyClass obj; // global object


int main()
{
    doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
}

위의 예제에는 using선언이나 지시문이 using없지만 컴파일러 doSomething()Koenig 조회MyNamespace 를 적용하여 네임 스페이스 에 선언 된 함수로 규정되지 않은 이름 을 올바르게 식별합니다 .

어떻게 작동합니까?

이 알고리즘은 컴파일러에게 로컬 범위뿐만 아니라 인수 유형이 포함 된 네임 스페이스도 확인하도록 지시합니다. 따라서 위 코드에서 컴파일러는 obj함수의 인수 인 객체 doSomething()가 네임 스페이스에 속하는 것을 발견합니다 MyNamespace. 따라서 해당 네임 스페이스를보고의 선언을 찾습니다 doSomething().

Koenig 조회의 장점은 무엇입니까?

위의 간단한 코드 예제에서 알 수 있듯이 Koenig 조회는 프로그래머에게 편의성과 사용 편의성을 제공합니다. Koenig 조회가 없으면 정규화 된 이름을 반복적으로 지정하거나 수많은 using선언을 사용하기 위해 프로그래머에게 오버 헤드가 발생합니다 .

Koenig 조회에 대한 비판이 필요한 이유는 무엇입니까?

Koenig 조회에 대한 과도한 의존은 시맨틱 문제로 이어질 수 있으며 때때로 프로그래머를 보호합니다.

std::swap두 개의 값을 바꾸는 표준 라이브러리 알고리즘 인의 예를 고려하십시오 . Koenig 조회를 사용하면 다음과 같은 이유로이 알고리즘을 사용할 때주의해야합니다.

std::swap(obj1,obj2);

다음과 같은 동작을 나타내지 않을 수 있습니다.

using std::swap;
swap(obj1, obj2);

ADL의 경우 어떤 버전의 swap함수가 호출되는지는 전달 된 인수의 네임 스페이스에 따라 다릅니다.

거기에 네임 스페이스를 존재하는 경우 A와 경우 A::obj1, A::obj2& A::swap()존재하는 다음 두 번째 예를 호출 발생합니다 A::swap()사용자가 원하는 것을하지 않을 수도 있습니다.

또한, 어떤 이유로 두 경우 A::swap(A::MyClass&, A::MyClass&)std::swap(A::MyClass&, A::MyClass&)정의, 후 첫 번째 예는 호출 std::swap(A::MyClass&, A::MyClass&)때문이 아니라 두 번째는 컴파일되지 않습니다 swap(obj1, obj2)모호 할 것이다.

하찮은 일:

“Koenig 조회”라고하는 이유는 무엇입니까?

전 AT & T와 Bell Labs의 연구원이자 프로그래머 인 Andrew Koenig에 의해 고안 되었기 때문 입니다.

더 읽을 거리 :



1 Koenig 조회의 정의는 Josuttis의 저서 인 The C ++ Standard Library : A Tutorial and Reference에 정의되어 있습니다.


답변

Koenig Lookup에서 네임 스페이스를 지정하지 않고 함수를 호출하면 함수의 이름 인수의 유형이 정의 된 네임 스페이스에서 검색됩니다. 그것은 또한으로 알려져 있습니다 이유입니다 인수 종속 이름 조회 짧은 단지로, ADL .

Koenig 조회로 인해 다음과 같이 작성할 수 있습니다.

std::cout << "Hello World!" << "\n";

그렇지 않으면 다음과 같이 작성해야합니다.

std::operator<<(std::operator<<(std::cout, "Hello World!"), "\n");

실제로 너무 많이 입력하고 코드가 정말 못 생겼습니다!

다시 말해 Koenig Lookup이 없으면 Hello World 프로그램 조차 복잡해 보입니다.


답변

어쩌면 그 이유부터 시작하는 것이 가장 좋을 것입니다.

네임 스페이스가 도입되었을 때, 별도의 라이브러리가 서로 간섭하지 않도록 네임 스페이스에 모든 것을 정의하는 것이 아이디어였습니다. 그러나 이것은 운영자에게 문제를 일으켰습니다. 예를 들어 다음 코드를보십시오.

namespace N
{
  class X {};
  void f(X);
  X& operator++(X&);
}

int main()
{
  // define an object of type X
  N::X x;

  // apply f to it
  N::f(x);

  // apply operator++ to it
  ???
}

물론 당신은 쓸 수 N::operator++(x)있었지만, 그것은 연산자 오버로드의 전체 지점을 물리 쳤을 것입니다. 따라서 컴파일러가 operator++(X&)범위 내에 있지 않다는 사실에도 불구하고 컴파일러를 찾을 수있는 솔루션을 찾아야 했습니다. 반면에 operator++, 호출을 모호하게 할 수있는 다른 관련없는 네임 스페이스에 정의 된 다른 것을 찾지 않아야 합니다 (이 간단한 예에서는 모호함이 없지만보다 복잡한 예에서는 그렇습니다). 해결책은 인수에 의존하기 때문에 (더 정확하게는 인수 유형에 따라) ARL (Argument Dependent Lookup)이었습니다. 이 계획은 Andrew R. Koenig에 의해 발명되었으므로 종종 Koenig 조회라고도합니다.

트릭은 함수 호출의 경우 일반 이름 조회 (사용 시점에서 범위에서 이름을 찾는 것) 외에도 함수에 지정된 인수 유형의 범위에서 두 번째 조회를 수행한다는 것입니다. 당신이 쓰는 경우에 따라서 위의 예에서 x++주, 그것은을 찾습니다 operator++전역 범위에 있지만, 추가의 유형이 범위뿐만 아니라 x, N::X정의 된, 즉,에 namespace N. 그리고 거기에서 일치하는 것을 발견 operator++하므로 x++작동합니다. 또 operator++다른 네임 스페이스에 정의는, 말 N2, 그러나 찾을 수 없습니다. ADL은 네임 스페이스로 제한되지 않기 때문에 in f(x)대신에 사용할 수도 있습니다 .N::f(x)main()


답변

내 의견으로는 그것에 관한 모든 것이 좋지는 않습니다. 컴파일러 공급 업체를 포함한 사람들은 때때로 불행한 행동으로 인해이를 모욕하고 있습니다.

ADL은 C ++ 11에서 for-range 루프를 대대적으로 검사합니다. ADL이 의도하지 않은 결과를 초래할 수있는 이유를 이해하려면 인수가 정의 된 네임 스페이스뿐만 아니라 인수의 템플리트 인수, 함수 유형의 매개 변수 유형 / 포인터 유형의 포인터 유형의 인수도 고려하십시오. 등등.

부스트를 사용하는 예

std::vector<boost::shared_ptr<int>> v;
auto x = begin(v);

사용자가 boost.range 라이브러리를 사용하는 경우 std::begin(ADL을 사용하여 std::vector) boost::begin찾 거나 (ADL을 사용하여 ) 찾게 되므로 모호한 결과가 발생했습니다 boost::shared_ptr.


답변