다음 macro는 array의 length를 구하는 것인데 해석이 되시나요?
...
안되신 분들을 위한 설명입니다. ;)
위 코드는 다음 두가지 사실만 알고 있다면 (비교적) 쉽게 이해됩니다.
sizeof는 function call syntax에 대해서도 동작하며 그 function의 return type에 대해 동작한다.
array type의 reference를 리턴하는 method의 signature는 다음과 같다.
이를 바탕으로 arraysizeof를 만들려면 char(&)[N]을 리턴하는 method를 만들면 되죠. 여기서 N은 array의 length.
위 함수는 T(&)[N]을 parameter로 받아 char(&)[N]을 리턴합니다. 물론 T(&)[N] parameter는 이 template method의 implicit instantiation이 동작하도록 하기 위해 필요합니다. 마지막으로 sizeof는 method body가 필요없으므로...
끝.
참고로 이런 코드가 필요한 이유는 널리 쓰이는 "sizeof(array) / sizeof(*array)" macro가 다음과 같은 경우 compile error없이 오동작하기 때문입니다.
이 코드에서 array는 pointer와 같이 취급되어 sizeof(array)는 sizeof(int*)가 됩니다.
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*)가 됩니다.
좋은 포스팅이네요. 그런데 저는 여기서 & 가 왜 필요한지 왜 어떤 & 는 괄호안에 있는지 잘 모르겠습니다. 설명좀 ^^
ReplyDelete아.. 포스팅에 엄청난 에러가 있었네요. 수정했습니다.
ReplyDelete괄호를 사용한 이유는 괄호 없는 T&[N]은 T reference type의 array란 의미가 되기 때문입니다.
아 잘 봤습니다. 하나 배웠네요.
ReplyDelete예로 드신 매크로를 사용하고 있었는데, 이제까지 저런 경우가 없어서 문제가 안 생겼었네요. 주의해야겠습니다.