[C++ STL] type_traits

오젼·2022년 9월 4일
0

[C++ STL]

목록 보기
9/11

is_integral

template <class T>
struct is_integral {
    static const bool value = false;
};

template <>
struct is_integral<bool> {
    static const bool value = true;
};

template <>
struct is_integral<char> {
    static const bool value = true;
};

template <>
struct is_integral<char16_t> {
    static const bool value = true;
};

이런 식으로 구현.

  • template type이 integral인지 확인.
    is_integral<type>::value로 접근해서 true, false 확인할 수 있음

enable_if

template <bool Cond, class T = void>
struct enable_if {
};

template <class T>
struct enable_if<true, T> {
    typedef T type;
};
  • SFINAE에 잘 이용되는 툴이 enable_if.
  • enable_if<is_integral<T>, T>::type 이런 식으로 사용.
  • bool이 false이면 치환 오류가 발생해서 오버로딩 실패하게 되고
  • bool이 true이면 enable_if<true, T>로 들어가서 enable_if<bool, T>::type으로 접근해서 해당 템플릿 타입을 사용할 수 있게 한다.

SFINAE

  • Substitution Failure Is Not An Error
  • https://modoocode.com/255
  • immediate context(함수 선언부라고 생각하면 될듯) 범위 내에서의 치환 오류는 컴파일 에러가 안 난다!
  • 치환 오류를 발생시키면 컴파일 에러는 안 나지만 함수 오버로딩군에서 제외 시킬 수 있고, 이로써 원하는 함수 오버로딩 매개변수를 명확하게 제시할 수 있게 된다.

ex)

explicit vector(
	size_type n,
    const value_type &val = value_type(),
	const allocator_type &alloc = allocator_type())
	: _allocator(alloc), _capacity(n), _size(n)
{
		_data = _allocator.allocate(n);
		for (int i = 0; i < n; i++)
			_data[i] = val;
} // fill

template <class InputIterator>
vector(
	typename ft::enable_if<!ft::is_integral<InputIterator>::value, InputIterator>::type first,
	InputIterator last,
	const allocator_type &alloc = allocator_type())
	: _allocator(alloc), _capacity(last - first), _size(last - first)
{
	_data = _allocator.allocate(_capacity);
	for (InputIterator it = first; it != last; it++)
		*(_data++) = *it;
} // range
  • vector의 fill constructorrange constructor는 매개변수가 두 개이며 (enable_if를 사용하지 않은 경우) 타입 또한 같아질 수 있다. range constructor가 템플릿 함수로 구현되어 있기 때문이다.
  • 예를 들어 vector(5,2)fill constructor로 value가 2이며 크기가 5인 vector를 생성하라는 뜻이지만 첫 번째 인자 5가 unsigned int가 아닌 signed int로 판단되고 fill constructor를 지나 range constructor로 일단 들어가 실행되게 된다.
  • 이를 막기 위해 이전에 구현해뒀던 ft::is_integral, ft::enable_if를 이용한다.
typename ft::enable_if<!ft::is_integral<InputIterator>::value, InputIterator>::type first
  • 첫 번째 인자가 size_type이 아닌 경우, 즉 ft::is_integral::value가 false인 경우에만 !ft::is_integral<InputIterator>::value가 true가 돼서 range constructor가 오버로딩 함수군에 포함되게 된다. 그렇지 않은 경우 Subsitution Failure가 되어 오버로딩 함수군에서 제거 되고 fill constructor가 올바르게 실행될 수 있다.

0개의 댓글