1. 템플릿 메타 함수
- 함수와 비슷하지만 값에 대한 연산이 아닌 타입에 대한 연산을 수행
- 음수인지 판별하는 함수 예시 코드
#include <iostream>
#include <type_traits>
//<>를 통해 함수 인자가 아닌 템플릿 인자를 전달
template <typename T>
void tell_type()
{
if (std::is_void<T>::value) std::cout << "T는 void ! \n";
else std::cout << "T는 void 가 아님\n";
}
int main()
{
tell_type<int>();
tell_type<void>();
return 0;
}
T 는 void 가 아님
T 는 void !
2. is_class
- 인자로 전달된 타입이 클래스인지 아닌지 확인하는 메타 함수
detail::test
를 통해 T
의 타입을 확인하고 해당 타입의 size를 통해 클래스인지 확인함
- 적절한
test
함수를 찾던 중 치환 요류가 발생하더라도 컴파일 오류를 발생시키지 않음
- 오버로딩 후보군에서 제외만 시킴(SFINAE)
3. enable_if
- SFINAE를 통해 조건에 맞지 않는 함수들을 오버로딩 후보군에서 쉽게 뺄 수 있도록 도와주는 템플릿 메타 함수
- 정의부
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
- T가 정수타입일 때만 오버로딩을 하고 싶다면
std::enable_if<std::is_integral<T>::value>::type
4. 특정 멤버 함수가 존재하는 타입 만을 받는 함수
- 해당 함수를 가지고 있는 구조체를 인자로 사용하는 함수를 만들면 됨
- 하지만 해당 함수를 가지고 있지 않은 클래스의 객체를 전달한다면 컴파일 오류가 발생함
func()
의 리턴 타입까지 강제하기 위해 enable_if
를 사용 가능
#include <iostream>
#include <type_traits>
// T 는 반드시 정수 타입을 리턴하는 멤버 함수 func 을 가지고 있어야 한다.
template <typename T, typename = std::enable_if_t<
std::is_integral_v<decltype(std::declval<T>().func())>>>
void test(const T& t) {
std::cout << "t.func() : " << t.func() << std::endl;
}
struct A {
int func() const { return 1; }
};
struct B {
char func() const { return 'a'; }
};
int main() {
test(A{});
test(B{});
}