2

다음 코드는 대부분 Piotr Skotnicki가 answer에서 가져온 것입니다. 람다 객체에 의해 생성하기 때문에,형식 매개 변수 이름을 변경하면 템플릿 대체가 실패합니다 - 컴파일러 버그?

#include <iostream> 

template <typename T> 
struct identity { using type = T; }; 

template <typename...> 
using void_t = void; 

template <typename F> 
struct call_operator; 

template <typename C, typename R, typename... A> 
struct call_operator<R(C::*)(A...)> : identity<R(A...)> {}; 

template <typename C, typename R, typename... A> 
struct call_operator<R(C::*)(A...) const> : identity<R(A...)> {}; 

template <typename F> 
using call_operator_t = typename call_operator<F>::type; 

template <typename, typename = void_t<>> 
struct is_convertible_to_function 
    : std::false_type {}; 

template <typename L> 
struct is_convertible_to_function<L, void_t<decltype(&L::operator())>> 
    : std::is_assignable<call_operator_t<decltype(&L::operator())>*&, L> {}; 

template <typename, typename = void_t<>> 
struct is_callable_object 
    : std::false_type {}; 

template <typename L> 
struct is_callable_object<L, void_t<decltype(&L::operator())>> 
    : std::true_type {}; 


int main() 
{ 
    auto x = []() {}; 
    std::cout << std::boolalpha << is_callable_object<decltype(x)>::value; 
    std::getchar(); 
} 

이 예상대로 true을 인쇄 : 나는 그것을 실험 내가 3

다음 코드를 고려 MSVC 14.0 업데이트에서 버그가 수 있도록 믿는 것을 발견 컴파일러는 operator()을 구현합니다.

의 지금 (내가 보는 것과, is_convertible_to_function 원인이 문제에 사용 된 유형 이름과 다른 무엇이든) TL에서 is_callable_object의 형식 매개 변수 이름을 변경하자.

template <typename, typename = void_t<>> 
struct is_callable_object 
    : std::false_type {}; 

template <typename T> 
struct is_callable_object<T, void_t<decltype(&T::operator())>> 
    : std::true_type {}; 

갑자기 false를 인쇄합니다. is_callable_object은 어떤 식 으로든 그것에 의존하지 않으므로 is_convertible_to_funtion은 중요하지 않습니다. 실제로 is_convertible_to_function을 제거하면이 문제가 사라집니다. 원하는 모든 유형 이름을 사용할 수 있습니다.

내가 말했듯이, 나는 이것이 버그라고 생각한다. 그래서이 질문이 C++ 표준의 기괴한 행동이 아님을 확인하고있다. 이에 대한 해결 방법은 매우 쉽습니다.

답변

2

표현식 sfinae는 msvc 2015에서 작동하지 않습니다. 작동하는 모든 경우는 우발적이며 신뢰할 수 없습니다. decltype은 msvc 2015에서 안정적으로 sfinae를 발생시키는 데 사용할 수 없습니다..

그만 두어 다른 해결책을 찾으십시오. 어쩌면 컴파일러 내장 함수를 사용해보십시오.

매개 변수 이름이 일치 할 때 우연히 작동한다고 가정하지 마십시오. 다른 기능이 작동하거나 약간 다른 프로그램에서 작동합니다.

해결 방법을 신뢰할 수 없습니다.

+0

귀하의 진술이 너무 극단적 인 것은 아닌지 궁금 해서요. 그러나 마이크로 소프트조차도 그것을 인정합니다. https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for- expression-sfinae-in-vs-2015-update-1 /. 아 글쎄, 계속 실험 해 볼께. 고마워. – szczurcio