2017-10-12 11 views
4

이 MWE를 호출 한 후 실패하지만 실패 static_assert 그럼에도 불구하고 놀라운 :noexcept 운영자는 인위적인 나타날 수 있습니다 포인터 - 투 - 회원 기능을

#include <utility> 

struct C { 
    void f() noexcept { } 
    using F = void(C::*)(); 

    static constexpr F handler() noexcept { 
    return &C::f; 
    } 

    void g() noexcept(noexcept((this->*handler())())) { 
    } 
}; 

int main() { 
    static_assert(noexcept(std::declval<C>().g())); 
} 

Wandbox 링크 : https://wandbox.org/permlink/a8HSyfuyX1buGrbZ

나는이 작업 할 기대 Clang하지만 Operator noexcept의 맥락에서 "this"와는 다른 처리 방식으로 인해 GCC가 아닙니다.

+0

귀하의 질문에 무엇입니까? – aschepler

+0

답변 중 하나가 당신의 질문에 대답하는 경우, 당신이 그것을 받아 들일 수 있습니다. 경우 둘 다 질문에 대답하지 못했습니다. 이유를 설명하여 대답을 향상시킬 수 있습니까? – Justin

+0

긴 지연에 대해 유감스럽게 생각합니다. 나는 그 대답에 만족하지 못했지만, 그 질문에 답을 한 후에 받아 들일 것입니다. 그러나 필자의 경우 "f"는 라이브러리 사용자가 전달한 템플릿 매개 변수이므로 멤버 함수에 대한 포인터의 noexcept 지정자를 올바르게 선언하려면 함수 유형의 noexcept-ness를 쿼리해야합니다. 안타깝게도 형식 별칭에 noexcept를 추가하더라도 F에 대한 별칭이 템플릿으로 만들어져 컴파일되지 않습니다. 이는 내부 컴파일러 오류를 발생시킵니다. 이것에 대한 Clang 버그를 게시 할 것입니다. – Jackie

답변

7

static_assert은 문자열 인수가 없으므로 C++ 17을 사용하고 있습니다. C++ 17에서는 noexcept이 형식 시스템의 일부가되었습니다. 즉, 주어진 의미는 다음과 같습니다.

using F = void(C::*)(); 

이 PMF는 noexcept이 아닙니다. 이 함수를 호출하면 noexcept(false) 멤버 함수를 호출하는 것과 같습니다.

using F = void(C::*)() noexcept; 

변화가 코드를 컴파일 할 수 있습니다 : 당신은 noexcept로 기능 유형을 표시해야

#include <utility> 

struct C { 
    void f() noexcept { } 
    using F = void(C::*)() noexcept; 

    static constexpr F handler() noexcept { 
    return &C::f; 
    } 

    void g() noexcept(noexcept((this->*handler())())) { 
    } 
}; 

int main() { 
    static_assert(noexcept(std::declval<C>().g())); 
} 

On Godbolt

3

fnoexcept이지만, 포인터가 아니다 . 따라서 g의 정의에서 this->*handler()noexcept이 아닌 PMF를 반환합니다 (noexcept 인 MF의 주소를 반환하기 때문에) (this->*handler())()을 작성하여 호출 할 때 noexceptnoexcept 절 있도록 false이 반환합니다.

을 5 행의 끝에 noexcept를 추가하고 작동합니다.