[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" };
참고
정상적으로
std::tuple의 template parameter 순서를 역순으로 뒤집는 또다른 구현 예
Last modified: 03 January 2024