질문의 역사: ADL(인수 의존 조회, Argument Dependent Lookup), 또한 코닝 조회(Koenig lookup)라고도 알려져 있으며, C++에서 연산자 오버로딩(특히 사용자 정의 타입에 대한 operator<< 및 operator>>)을 지원하기 위해 처음 등장했습니다. 목적은 네임스페이스와 사용자 정의 타입이 혼합된 경우 함수들을 올바르게 찾는 것입니다.
문제: 표준 함수 조회 메커니즘은 호출 지점과 다른 네임스페이스에 선언된 함수를 "인식하지 못할 수 있습니다". ADL은 이 문제를 해결합니다: 컴파일러는 함수 인수의 타입이 속한 네임스페이스를 고려하여 이름을 해석합니다. 이 메커니즘은 때때로 예상치 못한 오버로딩 선택이나 애매함을 초래할 수 있습니다.
해결 방법: 사용자 정의 네임스페이스의 객체인 인수를 가진 함수가 호출될 때, 컴파일러는 현재 범위뿐만 아니라 인수 타입과 연결된 모든 네임스페이스에서 적합한 오버로딩된 함수들을 찾습니다.
코드 예시:
namespace lib { struct Widget {}; void do_something(const Widget&) { std::cout << "Widget" << std::endl; } } using lib::Widget; void call(const Widget& w) { do_something(w); // do_something은 ADL을 통해 찾아진다 }
주요 특징:
두 네임스페이스에 같은 이름의 함수를 선언하고 두 번째 객체를 전달하면 어떤 것이 호출되나요?
인수의 네임스페이스에 있는 함수가 인수와 맞는다면 ADL 덕분에 선택됩니다:
namespace A { struct S {}; void f(const S&) { std::cout << "A!"; } } namespace B { struct S {}; void f(const S&) { std::cout << "B!"; } } A::S a; B::S b; f(a); // A::f가 ADL을 통해 호출된다 f(b); // B::f가 ADL을 통해 호출된다
ADL은 템플릿 함수와 함께 작동하나요?
네, 템플릿 함수가 인수 타입과 동일한 네임스페이스에 정의되어 있다면, ADL은 해당 타입으로 호출할 때 그것을 찾을 수 있습니다.
함수 포인터에 대해서도 ADL이 작동하나요?
아니요, ADL은 함수의 주소를 가져올 때(예: 함수의 주소를 취할 때) 적용되지 않습니다. 오직 함수가 직접 호출될 때만 적용됩니다.
프로젝트가 여러 서드파티 라이브러리를 연결했으며, 각각의 네임스페이스에 자신의 print()가 있었습니다. 주요 코드에서 다양한 클래스 객체로 print()를 사용했습니다. ADL로 인해 컴파일러가 잘못된 네임스페이스의 함수를 "선택하기" 시작했습니다.
장점:
단점:
자격 있는 호출(네임스페이스를 명시적으로 지정하는 것)을 사용 시:
lib::do_something(w); // 명확하게!
장점:
단점: