C++11~
enable_if
C++17~
enable_if_t
이건 사실 위의 enable_if 를 편히 쓸 수 있게 만들어 둔 것이다.
enable_if<?, ?>:: type
enable_if_t<?, ?>
위 두개는 같은 표현이다 (C++ 17에서는)
<type_traits> 에 정의된 클래스 템플릿.
해당 템플릿을 통해
1. 특정한 상황일 때 불리는 overload 된 function을 만들 수 있거나,
2. 특정한 상황일 때 특정한 return type을 가지는 function을 만들 수 있다.
enable_if 정의는 아래와 같이 정의되어있다.
template <bool _Test, class _Ty = void>
struct enable_if {}; // no member "type" when !_Test
template <class _Ty>
struct enable_if<true, _Ty> { // type is _Ty for _Test
using type = _Ty;
};
template <bool _Test, class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;
enable_if 의 앞쪽 template에 들어가는 것이 true가 되면, type이 뒤에 오는 template으로 정의가 된다.
enable_if 의 앞쪽 template에 들어가는 것이 false가 되면, type이 정의되지 않는다.
이 부분에서 결국 중요한건 type 이 정의되어 있느냐, 정의되어 있지 않느냐이다.
template으로 넘어온 앞의 것이 true이면 type이라는 using을 사용한다.
template으로 넘어온 앞의 것이 false이면 type이라는 using을 사용하지 않는다.
그래서 type을 사용하려고 할 때, 앞에가 true인지 false인지에 따라 빌드되는게 달라진다.
예제를 보자.
#include <iostream>
#include <type_traits>
template <typename T>
typename std::enable_if_t<std::is_same_v<T, int>, void>
print(T t)
{
std::cout << "print : " << t << std::endl;
}
int main()
{
print(42);
print("Hello, world!"); // 컴파일 에러!
return 0;
}
main을 확인해 보자.
print(42) - > arg == int
print("Hello, world!") -> arg == const char*
이런 식으로, print에 int 를 주거나 const char* 를 주고 있다.
print를 확인해 보자.
return type은
typename std::enable_if_t<std::is_same_v<T, int>, void> 이다.
먼저 enable_if_t 안을 확인하면
std::is_same_v<T, int>, void> 이다.
T가 만약 int라면 std::is_same_v<T, int> 가 true일 것이고,
int가 아니라면 false일 것이다.
그렇다면 int 를 넘겨주는 print는
typename std::enable_if_t<true, void>
const char*을 넘겨주는 print는
typename std::enable_if_t<false, void>
일 것이다.
근데 위에서 보면, 앞의 template 이 true인 것은 type이라는 using을 사용하지만,
false 인 것은 using을 사용하지 않는다. 즉 '없다'
결국, 해당 함수는 int parameter를 가진 것에 대해서만 만들어진다.
이 개념을 통하여, SFINAE를 편리하게 활용할 수 있다고 한다.
다만 위에서 봤듯이 코드가 좀 길어져서... C++ 20 이후부터는 concepts 라는 것을 활용한다고 하는데, 이건 또 공부해 봐야것다.
'C++ > 기타' 카테고리의 다른 글
[C++] DLL로 class export / import - 2 (0) | 2023.03.20 |
---|---|
[C++] DLL로 class export / import - 1 (0) | 2023.03.16 |
[C++ String] string 나누기. string split (0) | 2023.03.04 |
[C++ keyword] noexcept (0) | 2023.03.02 |
[C++ keyword] explicit 란? (4) | 2023.02.25 |