문제

다음 코드를 고려하십시오.

#include <stdio.h>

namespace Foo {
  template <typename T>
  void foo(T *, int) { puts("T"); }

  template <typename T>
  struct foo_fun {
    static void fun() { foo((T *)0, 0); };
  };
}

namespace Foo {
  void foo(int *, int) { puts("int"); }
}

using namespace Foo;

int main() {
  foo_fun<int> fun;
  fun.fun();
}

예상 출력은 무엇입니까? "t"또는 int?

하나의 컴파일러 (Apple의 Xcode 3.1.2에서 GCC 4.0.1) 출력 "int", 다른 두 컴파일러 (GCC 4.1.2 및 4.1.3) 출력 "t".

foo (t *, int) 버전 전에 foo (int *, int) 선언/정의를 이동하면 모든 출력 "int". 이 경우 과부하/전문화 순서가 현재 표준에 의해 정의됩니까?

도움이 되었습니까?

해결책

두번째 void foo(... 정의에서 보이지 않는 과부하 (및 전문화가 아님)입니다. foo_fun::fun 따라서 템플릿 정의의 맥락에서는 찾을 수 없습니다. 왜냐하면 T* 종속 유형, 해상도입니다 foo 표현에서 foo((T*)0, 0) 템플릿 인스턴스화 시간이 될 때까지 지연되며 인스턴스화의 컨텍스트도 고려됩니다. 그러나 표준의 14.6.4.2는 함수 이름이 자격이없는 ID 그러나 아닙니다 템플릿 -ID 그런 다음 비 ADL 조회의 경우 템플릿 정의 지점에서 볼 수있는 함수 만 고려됩니다. The의 기능 인수가 없습니다 Foo 네임 스페이스 따라서 인수 종속 조회가 발생하지 않으므로 템플릿 버전이 foo 비 테일 플레이트 오버로드가 아닌 호출됩니다.

이 답변에 대한 수정에 대한 Litb에게 감사드립니다.

아래와 같이 전문화 된 경우 템플릿 인스턴스화 시간에 전문화가 선택되면 기능 템플릿이 처음 인스턴스화되는 시점에서 관련 전문화가 보이는 한 전문화를 호출 할 수 있습니다. int.

namespace Foo {
    template<>
    void foo<int>(int *, int) { puts("int"); }
}

현재 표준의 14 장이지만 읽기 쉬운 것은 아닙니다 :)

편집 : 표준에서 가장 관련성이 높은 부분을 선택해야한다면 아마도 14.6 [temp.res] pra 9 일 것입니다. 이름이 템플릿-파라미터, 해당 이름에 대한 선언은 템플릿 정의에 이름이 나타나는 지점에서 범위에 있어야합니다. 이름은 그 시점에서 발견 된 선언에 구속 되며이 구속력은 인스턴스화 시점에서 볼 수있는 선언의 영향을받지 않습니다.

편집, 편집 : 그러나 14.6.4.2 [temp.dep.candidate]를 고려해야합니다. 모든 상호 의존성 때문에 표준을 시도하고 참조하는 것은 매우 어렵고 위험합니다.이 답변은 그 예입니다.

다른 팁

일반적으로 컴파일러의 두 버전 중에서 나중에 더 표준 일 가능성이 높습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top