2016-06-05 7 views
2

코드 :이상한 SFINAE 내가 SFINAE에 함께이 코드를 발견

template<int I> void div(char(*)[I % 2 == 0] = 0) { 
    // this overload is selected when I is even 
} 
template<int I> void div(char(*)[I % 2 == 1] = 0) { 
    // this overload is selected when I is odd 
} 

는 어떻게 작동합니까를? 이름없는 매개 변수 배열처럼 보이지만 과부하 해결에 하위 스크립트가 어떻게 도움이되는지 이해하지 못합니다.

답변

6

C++의 배열 경계는 0 일 수 없습니다. 표현식 (예 : I % 2 == 0)이 false 인 경우 해당 값이 0으로 변환되어 유형이 잘못되어 대체가 실패합니다.

기본적으로 std::enable_if의 난독 화 된 버전입니다.

1

이것은 다음과 같이 호출됨을 기억하십시오 : div<1234>() => 첫 번째 과부하가 호출됩니다.

경우에만 인수 볼 필요가 이해하기 : 이것은 문자의 배열에 대한 포인터를 의미

char(*)[I % 2 == 0] = 0 . 이 배열의 기본값은 0입니다. 즉, 할 수 있음을 의미합니다. char a[] = "hello world"; div<1234>(a);

I % 2 == 0은 컴파일 타임에 계산됩니다. 당신은 그것이 무엇을하는지 알아야합니다. 심지어 정수가이 사실을 만든다. 이상한 정수는 이것을 틀리게 만든다. True는 1로 평가되고, false는 0으로 평가됩니다. 그러나 요소가 0 인 배열과 같은 것은 없습니다. 이것은 SFINAE 오류라고 부르는 것입니다. 이는 템플릿의 공백을 적절히 대체 할 수 없다는 근본적인 오류라는 의미는 아닙니다. 템플릿이과 일치하지 않습니다.

0

T.C. 0 요소의 배열을 가질 수 없기 때문에 조건이 거짓 일 때 부울 false은 0으로 변환됩니다. 형식이 char (*) [0] (크기가 0 인 char 배열에 대한 포인터)가되어 SFINAE가 트리거됩니다.

지금보다 기존의 (읽을) 방법으로, 일반적으로 std::enable_if이 일을 할 것입니다 : Coliru 여기에 알 수 있듯이

template <int I, std::enable_if_t<I%2>* = nullptr> 
div() { 
    std::cout << "I (" << I <<") am odd." << std::endl; 
} 

template <int I, std::enable_if_t<!(I%2)>* = nullptr> 
div() { 
    std::cout << "I (" << I <<") am even." << std::endl; 
} 

.