More C++ Idioms (79. SFINAE - Substitution Failure Is Not An Error)

2024. 8. 28. 10:52프로그래밍 (확장)/More C++ Idioms

출처: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/SFINAE

 

More C++ Idioms/SFINAE - Wikibooks, open books for an open world

From Wikibooks, open books for an open world Jump to navigation Jump to search Prune functions that do not yield valid template instantiations from a set of overloaded functions. Substitution Failure Is Not An Error Strictly, SFINAE is a language feature a

en.wikibooks.org

 

https://en.cppreference.com/w/cpp/language/sfinae

 

SFINAE - cppreference.com

"Substitution Failure Is Not An Error" This rule applies during overload resolution of function templates: When substituting the explicitly specified or deduced type for the template parameter fails, the specialization is discarded from the overload set in

en.cppreference.com

 

 

SFINAE는 C++ 템플릿 프로그래밍에서 중요한 개념으로, "템플릿 치환 실패는 오류가 아니다"라는 의미로

 

 

  • 템플릿 인스턴스화 과정에서 템플릿 인수가 특정 요구 사항을 충족하지 못하여 치환에 실패하더라도, 컴파일러는 이를 오류로 간주하지 않는다. (템플릿 인스턴스화 중에 발생하는 오류는 컴파일러가 무시한다.)
  • 대신, 컴파일러는 해당 템플릿 특수화를 후보 목록에서 제외, 다른 적합한 특수화 모양을 찾는다.
  • 이를 통해 템플릿 설계, 함수 오버로딩에 에 유용하고 다양한 유형으로 코드를 작성할 수 있게 해준다.

 

enable_if로 많이 사용되었는데, SFINAE개념은 이 외에도 다양하게 활용되는데 이해를 돕기위해 enable_if로 예시를 만들어 보면 (enable_if는 별도로 정리할 예정)

 

아래 예시는 리턴타입에 enable_if를 사용해서 컴파일 타임에 조건을 조사해서 조사한 결과가 참이면 리턴 타입을 지정한 타입으로 치환하고, 거짓이면 타입이 없는 상태로 치환 된다. (즉 함수의 요건인 리턴타입이 없어 치환에 실패하게 된다. - 이는 에러를 발생시키지 않는데 이 것이 "템플릿 치환 실패는 오류가 아니다!")

 

* 예시는 ChatGPT로 생성

 

1. 타입 특성 검출

template<typename T>
std::enable_if_t<std::is_same_v<T, int>, bool> is_int(T) {
    return true;
}

template<typename T>
std::enable_if_t<!std::is_same_v<T, int>, bool> is_int(T) {
    return false;
}

 

is_int 함수는 T가 int일 때만 첫 번째 템플릿이 선택되고, 그 외의 경우 두 번째 템플릿이 선택된다.

 

 

2. 함수 오버로딩 (타입에 따라 다른 함수)

template<typename T>
std::enable_if_t<std::is_integral_v<T>, T> process(T value) {
    return value * 2;
}

template<typename T>
std::enable_if_t<!std::is_integral_v<T>, T> process(T value) {
    return value / 2;
}

process 함수는 T가 정수형 타입일 때는 * 2, 정수형이 아닐 때는 / 2를 하는 함수를 사용하게 된다.

 

이는 SFINAE를 어떻게 사용하는지 보여주고 다양한 활용은 나올 때 마다 이 포스팅과 연결해서 설명하는 것으로 정리할 예정.