Scribbles Help

[C++11] sizeof...(T)

sizeof...(T)은 C++11에 추가된 variadic template의 parameter pack 크기, 즉 type list의 길이를 가져오는 언어 키워드이다.

template parameter pack은 C++ 언어자체에 추가된 type list 지원기능이다. parameter pack은 일반 런타임 함수의 인수로는 전달할 수 없고 template parameter의 인수로써만 전달할 수 있다. parameter pack이 포함하는 타입을 조작하기 위해서는 약간 복잡한 C++ TMP 기교가 필요하다. sizeof...(T)는 이런 type list를 조작하는 데 유용하게 사용할 수 있는 기본도구이다.

기본적으로 아래와 같이 사용할 수 있다:

// basic usage example template <typename... TypeList> constexpr auto sizeofFuncParam(TypeList... tl) { return sizeof...(TypeList); } template <typename... TypeList> constexpr auto sizeofFuncParam1(TypeList... tl) { return sizeof...(tl); } // ... static_assert(sizeofFuncParam(1, 2, 3) == 3); static_assert(sizeofFuncParam(1, 2, 3, 4, 5) == 5); static_assert(sizeofFuncParam('a', 1, 1.0, "abc") == 4); static_assert(sizeofFuncParam1(1, 2, 3) == 3); static_assert(sizeofFuncParam1(1, 2, 3, 4, 5) == 5); static_assert(sizeofFuncParam1('a', 1, 1.0, "abc") == 4);

일반 function template뿐만 아니라 class template, member function template에서도 같은 방법으로 사용이 가능하다.

어떤이는 이거 가지고 뭐하겠냐고 생각할 수도 있겠다. 흠,... 현시점의 나의 C++ TMP 내공으로 생각해볼 수 있는 유용한 예제가 명확히 떠오르지는 않지만 다음과 같은 간단한(?) 활용을 생각해 볼 수 있었다.

주어진 std::tuple의 template parameter의 수를 얻어오기

// getting the number of tuple's template parameter size. template <typename... params> constexpr auto sizeofTuple(std::tuple<params...> const&) { return sizeof...(params); } template <typename Tuple> struct SizeOfTuple; template <typename... params> struct SizeOfTuple<std::tuple<params...>> { constexpr static size_t const value = sizeof...(params); }; // ... using tuple_3_t = std::tuple<int, char, std::string>; tuple_3_t t = { 1, '2', "abc" }; static_assert(sizeofTuple(t) == 3); static_assert(SizeOfTuple<tuple_3_t>::value == 3);

주어진 std::tuple의 template parameter를 역순으로 바꾼 tuple 타입 생성하기

아래 코드는 깔끔하지 못하다. 개선은 나중에 하고 일단 개념만 익히면 되겠다.

// getting a tuple type of which template parameters reversed to the given tuple. template <typename Tuple, size_t SizeOfTuple, typename IndexSequence> struct ReversedTupleImpl; template <typename... params, size_t SizeOfTuple, size_t... i> struct ReversedTupleImpl<std::tuple<params...>, SizeOfTuple, std::index_sequence<i...>> { typedef std::tuple< std::decay_t< decltype( std::get<SizeOfTuple - i - 1>(std::tuple<params...>()) ) >... > type; }; template <typename Tuple> struct ReversedTuple; template <typename... params> struct ReversedTuple<std::tuple<params...>> { constexpr static int const size = sizeof...(params); typedef typename ReversedTupleImpl<std::tuple<params...>, size, std::make_index_sequence<size>>::type type; }; // ... using tuple_3_t = std::tuple<int, char, std::string>; // ... // target reversed tuple using reversed_tuple_3_t = std::tuple<std::string, char, int>; static_assert(std::is_same<ReversedTuple<tuple_3_t>::type, reversed_tuple_3_t>::value, ""); using reversed_tuple_3_t_1 = ReversedTuple<tuple_3_t>::type; static_assert(std::is_same<std::string, std::tuple_element_t<0, reversed_tuple_3_t_1>>::value, ""); reversed_tuple_3_t_1 reversedT = { "abc", '2', 1 }; std::cout << std::get<0>(reversedT) << std::endl; std::cout << std::get<1>(reversedT) << std::endl; std::cout << std::get<2>(reversedT) << std::endl; // this doesn't work. it's expected. //reversed_tuple_3_t_1 reversedT1 = { 1, '2', "abc" };

참고

Last modified: 03 January 2024