2017-05-03 10 views
8

문제점이 this과 매우 비슷합니다.조건부 noexcept 및 과부하와 일치하지 않음

즉, noexcept 인 경우 noexceptmagic 메서드가 있습니다.

이상한 일이 "다른 방법은"두 과부하를 가지고 있으며, 컴파일러 magicnoexcept -ness을 결정하는 제 오버를 선택한다. magic가 나중에 호출 될 때

는 그러나 과부하라고하지만, magicnoexcept -ness은 동일하게 유지!

여기에 내가 이해부터 wandbox link

입니다 :이 시점에서 컴파일러에 의해 알려져 있지 user_method(dummy2) 때문에 다시

  • adl_caller(..., priority_tag<0>) noexcept에 떨어질

    1. noexcept(magic(dummy2{})) 전화
    2. noexcept(noexcept(adl_caller(...)).

    하지만 충분히 좋지 만, user_method(dummy2)은 3 줄을 어떻게 호출합니까? 표준이 의도 한 것입니까?

    죄송합니다. 충분히 명확하지 않으면 죄송합니다.

    #include <iostream> 
    
    template <unsigned N> struct priority_tag : priority_tag<N - 1> {}; 
    template <> struct priority_tag<0> {}; 
    
    template <typename T> 
    auto adl_caller(T t, priority_tag<1>) noexcept(noexcept(user_method(t))) 
        -> decltype(user_method(t)) { 
        std::cout << "first adl_caller overload" << std::endl; 
        user_method(t); 
    } 
    
    // tricky noexcept ... 
    template <typename T> void adl_caller(T, priority_tag<0>) noexcept { 
        std::cout << "second adl_caller overload" << std::endl; 
    } 
    
    template <typename T> 
    void magic(T t) noexcept(noexcept(adl_caller(t, priority_tag<1>{}))) { 
        adl_caller(t, priority_tag<1>{}); 
    } 
    
    struct dummy {}; 
    struct dummy2 {}; 
    
    // un-commenting this line makes the above call to cout print '0' 
    // void user_method(dummy2); 
    
    void user_method(dummy) 
    { 
        // user_method(dummy2) is declared after this point 
        // this line prints '1', since magic falls back to the second adl_caller overload 
        std::cout << "noexcept?: " << noexcept(magic(dummy2{})) << std::endl; 
        std::cout << "dummy method called" << std::endl; 
        // however, the first adl_caller overload is called here ... 
        magic(dummy2{}); 
    } 
    
    void user_method(dummy2) 
    { 
        std::cout << "dummy2 method called" << std::endl; 
    } 
    
    int main() 
    { 
        magic(dummy{}); 
    } 
    
  • 답변

    6

    [temp.point]/8 :

    함수 템플릿의 특성화 [...] 수도 는 변환 부 내에 인스턴스화 여러 지점을 가지고, 상기 인스턴스의 점 이외에 , 번역 단위 내에 인스턴스화 지점이있는 특수화의 경우 번역 단위의 끝도 인스턴스화 지점으로 간주됩니다. [...] 두 개의 다른 점이 템플릿 정의에 one-definition 규칙에 따라 다른 의미를 부여하면 프로그램이 잘못 구성되어 진단이 필요하지 않습니다. .

    [temp.dep.candidate] 비교해

    후위 표현 종속 이름 함수 호출에 대한

    가 후보 함수 통상 조회 규칙 를 사용하여 발견된다 ([basic.lookup.unqual ], [basic.lookup.argdep]) :

    • 비정규 화 된 이름 검색을 사용하는 부분에서는 재미 만 있습니다 템플리트 정의 컨텍스트의 선언이 발견됩니다.관련된 네임 스페이스를 사용하여 검색의 부분에 대한

    • 은 ([basic.lookup.argdep])는, 템플릿 정의 컨텍스트 또는 템플릿 인스턴스화 컨텍스트 중 검색된 만 함수 선언이 발견된다.

    호출이 잘못 형성 될 것이다 또는 더 나은 경기를 모두 변환 장치, 다만 고려하지 에서이 네임 스페이스의 소개 외부 링크 모든 기능 선언으로 간주 관련 네임 스페이스 내에서 조회를 가지고 찾아 낼 경우 템플릿 정의 및 템플리트 인스턴스화 컨텍스트에서 이라는 선언이 발견되면 프로그램에 정의되지 않은 동작이 적용됩니다 ( ).

    +0

    나는이 단락의 일부분을 이해한다고 생각하지만, 나에게 너무 애매하다. 내 예제에는 하나의 TU 만 있고 외부 링키지 함수는 없습니다. 마지막 단락은 연결된 코드와 어떤 관련이 있습니까? 제가 정확하게 이해한다면, '마법'방법은 첫 단락에 연결되어 있습니다, 그러나 나는 정확한 이유를 파악하는 데 약간의 어려움이 있습니다. 표준 발췌에 대해 감사드립니다. – Dante