0

I see this code in gtest source file. this snippet is used to generate a template whose template variable is a sequence of integer. can anybody explain how this works?

template <size_t... Is> struct int_pack { typedef int_pack type; };

template <class Pack, size_t I>
struct append;
template <size_t... Is, size_t I>
struct append<int_pack<Is...>, I> : int_pack<Is..., I> {};

template <size_t C>
struct make_int_pack : append<typename make_int_pack<C - 1>::type, C - 1> {};
template <> struct make_int_pack<0> : int_pack<> {};

we can use make_int_pack<5>() to generate a class instance (int_pack<0,1,2,3,4>()) which is further used to extract 0,1,2,3,4 to do something.

2

1 Answer 1

1

The construction is done with recursive substitution:

make_int_pack<5> derives from append<typename make_int_pack<5-1>::type,5-1>.

But make_int_pack<5-1>::type is make_int_pack<4>::type.

But make_int_pack<4>::type is the definition from append<typename make_int_pack<4-1>::type,4-1>, and so on.

So make_int_pack<5> derives from

  append<append<append<append<append<int_pack<>,0>,1>,2>,3>,4>

, which derives from int_pack<0,1,2,3,4>.

To use this int_pack we have to do something like pattern matching (c++11).

template<class T>struct test{};

template<size_t ... Is>
struct test<int_pack<Is...>>{
    // use template parameter pack
};

We could then use the static members of test<make_int_pack<5>> as result of some compiletime compilation or complex type construction.

Another possible way is to have

template<size_t... Is>
size_t test_fun(int_pack<Is...>);

,which would be called like test_fun(make_int_pack<5>());

Edit:

I'm wondering why there's two append struct, what's the difference between them?

You want to be able to write append<int_pack<0,1,2,3>,42>. Therefor append has to take two template parameters. That is your first declaration.

template<class T,size_t i> struct append{};

But actually you do not need the type int_pack<0,1,2,3> but the template paramter pack used. In c++ we have partial template specialization. If the type T happends to be an int_pack we use the special (second) declaration. In this way we can kind of pattern match the templated type T and get the template parameters used do define the int_pack.

template<size_t ... Is,size_t i>
struct append<int_pack<Is...>,i> : int_pack<Is...,i>{};

what's the meaning of append,0> ?

This will fall in the second case. We have an empty template parameter pack, since the brackets are empty int_pack<>. So we derive from int_pack<0> and therefor our append<int_pack<>,0>::type is int_pack<0>.

So in summary: look at template parameter packs and partial template specialization. When working with types it is basicly just substitution of expressions.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the reply, I'm wondering why there's two append struct, what's the difference between them. what's the meaning of append<int_pack<>,0> ? Any reply is appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.