>

sin 의 템플릿 버전을 제공하려는 사용자 정의 클래스가 있습니다  기능-나는 그것을 foo 라고 불렀다.  내 최소 검증 가능한 reporduction에서. 다른 곳의 템플릿 메타 프로그래밍으로 인해 sin 에 유리합니다.  일반 sin 와 이름이 같은 함수  다른 유형에서만 동일한 작업을 수행하는 것처럼 작동합니다.

그러나 다음은 컴파일되지 않습니다 :

#include <cmath>
#include <iostream>
#include <cstdlib>
namespace test
{
    template <std::size_t size>
    class foo
    {
    };
    template <std::size_t size>
    void sin(const foo<size>& f)
    {
    }
    template <class T>
    void bar(const T& x)
    {
        using namespace ::std;
        sin(x);
    }
}
int main()
{
    test::bar(0.5);
    std::cout << "Done...";
    std::getchar();
    return EXIT_SUCCESS;
}

다음 컴파일러 오류가 발생합니다 :

..\test\problem.cpp(23,3): error: no matching function for call to 'sin'
                sin(x);
                ^~~
..\test\problem.cpp(29,8): note: in instantiation of function template specialization 'test::bar<double>' requested here
        test::bar(0.5);
              ^
..\test\problem.cpp(14,7): note: candidate template ignored: could not match 'foo<size>' against 'const double'
        void sin(const foo<size>& f)
             ^
1 error generated.

이것에 놀랐습니다. bar 를 얻는 방법이 있습니까  템플릿 메타 프로그래밍 핵을 사용하지 않고 컴파일하여 여러 버전의 bar 를 만들 수 있습니다. ?

Clang 9 및 MSVC 2019에서 실패합니다.

  • 답변 # 1

    사용 지시문과 사용 선언에는 차이가 있습니다. 와이즈 비즈  using 지시문입니다. 규정되지 않은 이름 조회와 관련하여 using 지시문은 기본적으로 이름 조회를 전달하여 네임 스페이스 using namespace ::std; 도 검색합니다.  포인트 이름 조회에서 이름을 찾을 수없는 경우 지시문이 포함 된 네임 스페이스와 지시문 [namespace.udir]/2로 지정된 네임 스페이스에 모두 근접한 네임 스페이스에 도달합니다. 귀하의 경우 이는 이름 조회가 ::std 를 찾기 전에 글로벌 네임 스페이스에 도달해야 함을 의미합니다 . 그러나 이름 조회는 네임 스페이스 ::std::sin 에 도달합니다.  먼저 test 라는 함수를 포함합니다. 을 찾은 다음 [basic.lookup.unqual]/1 찾고있는 것을 찾았으므로 중지하십시오. 당신이 원하는 것은 사용 선언입니다 :

    sin
    
    

    using 지시문과 달리 using 선언은 선언 된 이름이 using 선언이있는 범위 [namespace.udecl]/1에 직접 도입됩니다. 이는 template <class T> void bar(const T& x) { using std::sin; sin(x); } 를 의미합니다.  바로 찾을 수 있습니다. 이제 정규화되지 않은 일반 이름 조회에서 std::sin 를 찾을 수 없습니다.  더 이상 사용 선언 후 블록 범위 내에서. 그러나 인수 종속 이름 검색 [basic.lookup.argdep] 덕분에 test::sin   test::sin 의 경우 과부하 세트를 다시 찾음   T 의 사례입니다 …

  • 답변 # 2

    (a) 의견과 (b) 의견에 연결된 답변을 바탕으로 한 '빠른 수정'이 있습니다. test::foo 의 최소 버전  기능은 다음과 같습니다.

    bar
    
    

    void bar() { ::sin(0.5); // Without "::" your templated "test::sin" hides the global namespace // version - which is here referenced EXPLICITLY. }

  • 이전 multithreading - Java의 스레드가 최종 필드를 캐시 할 수 있습니까?
  • 다음 C에서 int 데이터 유형에 pow ()가 작동합니까?