반응형

C++11 표준 type traits

  • 변형된 타입을 얻는 traits

    • typename remove_pointer<T>::type;

    • remove_pointer_t<T> n; // C++14

  • 타입의 정보를 조사하는 traits

    • bool b = is_pointer<T>::value;

    • bool b = is_pointer_v<T>;  // C++17

    • 함수 오버로딩 사용(true_type, false_type) 활용

  • 간소화된 버전

    • C++14 기본 제공

      • remove_pointer_t<T> n;

    • C++17 기본 제공

      • bool b = is_pointer_v<T>;

#include <iostream>
#include <type_traits>
using namespace std;

//using을 사용해서 간소화 가능
template<typename T>
using remove_pointer_type = typename remove_pointer<T>::type;

// C++17에서는 variable template을 사용해서 간소화 가능
//template<typename T>
//inline constexpr bool is_pointer_v = is_pointer<T>::value;

template<typename T> void foo(T a)
{
    // 포인터를 제거한 타입 반환
    typename remove_pointer<T>::type rawType;
    remove_pointer_type<T> rawType2;

    // 포인터 타입 여부 확인
    bool isPointer = is_pointer<T>::value;
}
int main()
{
    int n = 0;
    foo(&n);
}

 

C++11 표준 type_traits 예제

  • is_array<T>::value : 배열 확인

  • extent<T, 0>::value : 배열 각 차원의 요소 수 

  • is_same<T, U>::value : 타입 같음 비교

  • remove_cv<T, U>::type : const, volatile 속성 제거(타입 비교시 이용)

  • decay<T, U>::type : 배열을 포인터화 사용 필요 시

#include <iostream>
#include <type_traits>
using namespace std;

// 배열 정보 조사하기
// array => pointer : decay
template<typename T> void foo(T& a)
{
    if (is_array<T>::value)
    {
        cout << "array" << endl;

        cout << extent<T, 0>::value << endl;
        cout << extent<T, 1>::value << endl;
    }
}

template<typename T, typename U> void hoo(T a, U b)
{
    // 두 타입 비교
    bool ret1 = is_same<T, U>::value;

    // 배열일 경우 포인터화 비교
    bool ret2 = is_same<typename decay<T>::type, typename decay<U>::type>::value;

    // const, volatile 제거 후 비교
    bool ret3 = is_same<typename remove_cv<T>::type, typename remove_cv<U>::type>::value;

    cout << ret1 << endl;
    cout << ret2 << endl;
    cout << ret3 << endl;
}

int main()
{
    int x = 1;
    const int cx = 1;
    int* xp = &x;
    int a[3][2] = { 1,2,3,4,5,6 };
    foo(a);
    hoo(x, cx);
}
반응형

반응형

type traits 개념

  • 컴파일 타임에 타입에 대한 정보를 얻거나 변형된 타입을 얻을때 사용하는 도구(메타 함수)

  • <type_traits> 헤더로 제공됨(c++11)

type query를 위한 type traits 만드는 방법

  • 메인 템플릿(Primary template)에서 false 반환( value = false )

  • 부분 특수화(Partial specialization)에서 true 반환( value = true )

 

is_pointer 예제

  • 간단히 템플릿 파라미터 T가 포인터 타입 여부 확인 도구

  • 메인 템플릿(Primary template)에서 false 반환( value = false )
  • 포인터 타입용 부분 특수화(Partial specialization)에서 true 반환( value = true )
#include <iostream>
#include <type_traits>
using namespace std;

template<typename T> struct is_pointer_custom
{
    enum { value = false }; 
};

// 포인터 타입에 대해서 부분 특수화 필요
template<typename T> struct is_pointer_custom<T*>
{
    enum { value = true };
};

template<typename T> void foo(T v)
{
    if (is_pointer_custom<T>::value)
        cout << "pointer" << endl;
    else
        cout << "not pointer" << endl;
}

int main()
{
    int n = 3;
    foo(n);
    foo(&n);
}

 

is_pointer 개선 예제

  • c++11 기준 코드 개선
  • 좀더 다양한 포인터 타입 지원(const, volatile, const volatile)
#include <iostream>
#include <type_traits>
using namespace std;

template<typename T> struct is_pointer_custom
{
    //enum { value = false }; 
    static constexpr bool value = false; // c++11
};

// 포인터 타입에 대해서 부분 특수화 필요
template<typename T> struct is_pointer_custom<T*>
{
    //enum { value = true };
    static constexpr bool value = true; // c++
};

// 포인터 타입에 대해서 부분 특수화 필요
template<typename T> struct is_pointer_custom<T* const>
{
    //enum { value = true };
    static constexpr bool value = true; // c++
};

// 포인터 타입에 대해서 부분 특수화 필요
template<typename T> struct is_pointer_custom<T* volatile>
{
    //enum { value = true };
    static constexpr bool value = true; // c++
};

// 포인터 타입에 대해서 부분 특수화 필요
template<typename T> struct is_pointer_custom<T* const volatile>
{
    //enum { value = true };
    static constexpr bool value = true; // c++
};

int main()
{
    cout << is_pointer_custom<int>::value << endl;
    cout << is_pointer_custom<int*>::value << endl;
    cout << is_pointer_custom<int* const>::value << endl;
    cout << is_pointer_custom<int* volatile>::value << endl;
    cout << is_pointer_custom<int* const volatile>::value << endl;
    cout << is_pointer_custom<int* volatile const>::value << endl;
}
반응형

+ Recent posts