C++ of the Day #7 - ADL (Argument Dependent Lookup)

Question

오늘 내용은 다시 뉴스그룹에서 하나 가지고 왔습니다. ((comp.lang.c++.moderated:template parameter's namespace exposed?))
namespace N {
  class A {
  };

  template <class T>
  T1 operator + (T1 op1, T2 op2) { return op1; }
  }
}
template <class T>
class B {
};

int main() {
  N::A a1, a2;
  a1 + a2; // works as it should

  B<N::A> b1, b2;
  b1 + b2; // oops, this one compiles too!

  B<int> b3, b4;
  b3 + b4; // no match for operator +, just the way it should be
}
여기서 질문은?
  1. 왜 두번째의 b1 + b2 가 컴파일이 정상적으로 되는가?
  2. B 클래스가 있는 전역 영역에는 operator + 가 없는데...
입니다.


Answer

일단 문제를 파악하기 위해서는 ADL ((Argument Dependent Lookup 또는 Argument Dependent Name Lookup. 초기에는 규칙을 만든 사람의 이름을 따서 Koenig Lookup이라고 불렸었습니다.)) 에 대해서 알고 있어야 합니다. 자세한 내용은 Name Lookup이라는 글을 참고하시고요.

그럼 이제 찾아봐야 할 내용은 template parameter도 ADL의 규칙에 포함되는가 여부인데요 C++98에 보면 3.4.2.2절의 마지막 부분에 다음과 같은 내용이 있습니다.
--- If T is a template id, its associated namespaces and classes are the namespace in which the template is defined; for member templates, the member template’s class; the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters); the namespaces in which any template template arguments are defined; and the classes in which any member templates used as template template arguments are defined. [Note: nontype template arguments do not contribute to the set of associated namespaces. ]
이제 왜 두번째의 b1 + b2 가 정상적으로 컴파일이 되야 하는지 모두 확인되었네요. ;-)

이 문제의 교훈은 아무리 namespace안이라 하더라도 모든 타입에 적용될 수 있는 함수의 사용은 다른 namespace에 있는 함수와 ADL 규칙에 의해 충돌할 수 있으므로 피해야 한다는 것이겠네요.

Comments

Popular Posts