일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 텍스트북
- 42seoul
- 정렬
- adminbro
- 부동소수점
- c++
- 레이캐스팅
- 42서울
- 어셈블리
- enable_if
- 쿠버네티스
- mistel키보드
- Cloud Spanner
- 스타트업
- 엣지컴퓨팅
- 파이썬
- 프라이빗클라우드
- schema first
- psql extension
- 이노베이션아카데미
- 자료구조
- SFINAE
- 창업
- uuid-ossp
- raycasting
- 스플릿키보드
- 어셈블리어
- 도커
- 동료학습
- GraphQL
- Today
- Total
written by yechoi
[C++] SFINAE 와 enable_if의 사용법 본문
SFINAE란
Substition Failure Is Not An Error의 약자이다. 템플릿 인자 추론에서, C++ 컴파일러는 적합한 오버로딩 함수를 찾는다. 그 과정에서 함수 템플릿을 인스턴스화할 때, 인자나 결과가 유효하지 않다면 '컴파일 에러'를 뱉는 대신에 오버로드 결과물에서 해당 인스턴스화한 것을 지운다.
무슨 의미인지는 코드 예시를 보며 확인해본다.
long multiply(int i, int j) { return i * j; }
template <class T>
typename T::multiplication_result multiply(T t1, T t2)
{
return t1 * t2;
}
int main(void)
{
multiply(4,5);
}
위 코드에서 단순 multiply
함수가 있고, 템플릿화한 함수가 있다. multiply
함수를 main에서 호출하면 첫번째 multiply
함수가 더 적합하더라도 컴파일러는 템플릿화한 함수를 인스턴스화하려고 시도한다.
이 과정에서 int::multiplication_result
라는 유효하지 않은 자료형이 생성된다. 그렇지만 SFINAE로 인해, 유효하지 않은 인스턴스화는 자동으로 무시된다.
SFINAE는 컴파일 타임에 프로퍼티를 결정하는 데 사용되고는 한다.
SFINAE를 가능케 하는 구문, enable-if
SFINAE를 코드로 구현할 수 있도록 하는 구문이 enable-if
다. enable_if
는 아래처럼 구현될 수 있다.
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
enable_if
의 템플릿 첫번째 인자로 true
가 오면, enable_if
의 구조체 안에는 type이라는 자료형이 생긴다. 따라서 enable_if
의 템플릿 첫번째 인자로 boolean을 반환하는 구문을 넣어두고 해당 구문에서 판별을 요청하면, 결과값에 따라 type이 생기거나 생기지 않는 것을 이용할 수 있다.
아래는 이에 대한 예시다.
template<typename T, std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& bar) { isInt(); }
is_integral
은 T가 integral 계열인지 true, false로 반환한다. integral 계열일 때만 ::type
호출이 가능하다. 그러니까 integral 계열이 아니라면, 이 foo 함수는 적합하지 않은 것으로 판단하고 인스턴스화하지 않고 넘어간다.
참고로 템플릿의 두번째 인자인 std::enable_if<std::is_integral<T>::value, int>::type
는 = 0
으로 디폴트 값이 정해져있다. 그러니까 두번째 인자는 굳이 입력하지 않고 foo< int >( 1 );
이런식으로 호출이 가능하다. 디폴트 값을 설정해놓지 않았더라면, 템플릿에서는 두개의 변수를 필요로 했을 것이다.
🔗 [stackoverflow] How Does std::enable_if work?🔗 [wikibooks] SFINAE