arraysizeof macro

다음 macro는 array의 length를 구하는 것인데 해석이 되시나요?
template <typename T, size_t N>
char (&Helper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(Helper(array)))

...

안되신 분들을 위한 설명입니다. ;)

위 코드는 다음 두가지 사실만 알고 있다면 (비교적) 쉽게 이해됩니다.

sizeof는 function call syntax에 대해서도 동작하며 그 function의 return type에 대해 동작한다.
int foo() { return int(); }
...
sizeof(foo()) == sizeof(int)

array type의 reference를 리턴하는 method의 signature는 다음과 같다.
char (&bar)[10]() { ... }

이를 바탕으로 arraysizeof를 만들려면 char(&)[N]을 리턴하는 method를 만들면 되죠. 여기서 N은 array의 length.
template <typename T, size_t N>
char (&Helper(T (&array)[N]))[N] {
...
}

위 함수는 T(&)[N]을 parameter로 받아 char(&)[N]을 리턴합니다. 물론 T(&)[N] parameter는 이 template method의 implicit instantiation이 동작하도록 하기 위해 필요합니다. 마지막으로 sizeof는 method body가 필요없으므로...
template <typename T, size_t N>
char (&Helper(T (&array)[N]))[N];

끝.

참고로 이런 코드가 필요한 이유는 널리 쓰이는 "sizeof(array) / sizeof(*array)" macro가 다음과 같은 경우 compile error없이 오동작하기 때문입니다.
void foo(int array[]) {
int size = sizeof(array);
}

이 코드에서 array는 pointer와 같이 취급되어 sizeof(array)는 sizeof(int*)가 됩니다.

Comments

  1. 좋은 포스팅이네요. 그런데 저는 여기서 & 가 왜 필요한지 왜 어떤 & 는 괄호안에 있는지 잘 모르겠습니다. 설명좀 ^^

    ReplyDelete
  2. 아.. 포스팅에 엄청난 에러가 있었네요. 수정했습니다.

    괄호를 사용한 이유는 괄호 없는 T&[N]은 T reference type의 array란 의미가 되기 때문입니다.

    ReplyDelete
  3. 아 잘 봤습니다. 하나 배웠네요.
    예로 드신 매크로를 사용하고 있었는데, 이제까지 저런 경우가 없어서 문제가 안 생겼었네요. 주의해야겠습니다.

    ReplyDelete

Post a Comment

Popular Posts