반응형

is_array 예제

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

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

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

  • 타입을 정확히 알아야 함

    • int x[3]; 에서 x는 변수 이름, 변수 이름을 제외한 나머지 요소(int[3])이 타입임

  • unknown size array type(T[])에 대해서도 부분 특수화가 필요함

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

template<typename T> struct is_array_custom
{
    static constexpr bool value = false;
};

// 크기를 알 수 있는 배열의 부분 특수화
template<typename T, size_t N>
struct is_array_custom<T[N]>
{
    static constexpr bool value = true;
};

// 크기를 알 수 없는 배열의 부분 특수화
template<typename T, size_t N>
struct is_array_custom<T[N]>
{
    static constexpr bool value = true;
};

template<typename T> void foo(T& a)
{
    // 크기를 알 수 있는 배열 확인
    if (is_array_custom<T>::value)
        cout << "array" << endl;
    else
        cout << "not array" << endl;
      
    // 크기를 알 수 없는 배열을 사용하는 패턴도 존재함
    //if (is_array_custom<int[]>::value)
}

int main()
{
    int x[3] = { 1, 2, 3 };
    foo(x);
}

 

is_array 배열 크기 구하기

  • 부분 특수화로 배열의 크기도 구할 수 있음

    • c++11 extent<T, 0>::value 존재

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

template<typename T> struct is_array_custom
{
    static constexpr bool value = false;
    static constexpr size_t size = -1;
};

//사이즈를 알 수 있는 배열에 대한 부분 특수화에서 N이 배열의 크기
template<typename T, size_t N>
struct is_array_custom<T[N]>
{
    static constexpr bool value = true;
    static constexpr size_t size = N;
};

template<typename T> void foo(T& a)
{
    if (is_array_custom<T>::value)
        cout << "size of array : " << is_array_custom<T>::size << endl;
}

int main()
{
    int x[3] = { 1, 2, 3 };
    foo(x);
}
반응형

반응형

배열의 특징

  • 자신과 동일한 타입으로 초기화 될 수 없다.
  • 배열의 이름은 배열의 첫번째 요소의 주소로 암시적 형 변환 된다.
  • 배열을 가리키는 참조를 만들 수 있다.

함수 템플릿을 만들때

  • 배열을 값으로 받으면 T는 요소 타입의 포인터로 결정된다.
  • 배열을 참조로 받으면 T는 배열 타입으로 결정된다.
#include <iostream>

template<typename T>
void foo(T a)
{

}

template<typename T>
void goo(T& a)
{

}

int main()
{
    int x[3] = { 1,2,3 };

    foo(x); 
    goo(x);
}

 

관련 예제

  • 문자열의 타입 : char 배열
  • 문자열을 값으로 받으면 T는 const char* 결정되고, 참조로 받으면  const char[]로 결정된다.
  • 크기가 다른 배열은 다른 타입이다.
#include <iostream>

template<typename T>
void foo(T a, T b)
{

}

template<typename T>
void goo(T& a, T& b)
{

}

int main()
{
    foo("orange", "apple"); // ok
    goo("orange", "apple"); // error
}

 

반응형

반응형

배열의 이름과 주소

일반적으로 데이터 타입을 뺀 나머지는 변수명이라 할 수 있다.

int i에서 int를 빼면 i가 변수명이다. 그리고 데이터 타입에 *붙여서 선언하면 주소를 담을 수 있는 포인터 변수를 선언 할 수 있다. 그러면 배열을 어떨까?

 

int x[3] 에서 int[3] 뺀 나머지인 x가 동일하게 변수명이다. 그러면 포인터 변수는 마찬가지로 x 변수에 *만 붙이면 배열의 포인터 주소가 되는 것일까?

 

대부분 배열의 주소는 첫번째 요소의 주소로 많이 알고 있다. 하지만 배열의 주소와 첫번째 요소의 주소는 같으면서도

다르므로 명확히 구분해서 사용할 필요가 있다.

#include <iostream>

int main()
{
    int i = 1;
    int *px = &i;

    int x[3] = { 1, 2, 3 };
    int *p1 = x; // 일반적으로 생각하는 배열의 주소(묵시적으로 첫번째 요소의 주소로 형변환 됨)
    int(*p2)[3] = &x; // 정확한 배열의 주소(요소가 모두 포함된 전체 컨테이너의 주소)

    // + 1 연산을 하면 기본적으로 데이터 타입 사이즈 만큼 증가된 메모리 주소를 가르침
    printf("%p, %p\n", p1, p1 + 1); // 배열의 첫번째 요소의 주소에서 데이터 사이즈인 4바이트 증가
    printf("%p, %p\n", p2, p2 + 1); // 요소가 3개인 배열의 주소에서 데이터 사이즈인 12바이트 증가
}

 

반응형

+ Recent posts