0

I'm trying to reverse the order of a template-variadic std::size_t parameter sequence, based on an answer found in a previous thread. But for some reason it doesn't work.

Here's a regular variadic print function:

template<typename = void>
void print(void)
{
    std::cout << std::endl;
}

template<typename... T>
void print(std::size_t index, T... indexes)
{
    std::cout << index << ' ';
    print(indexes...);
}

And here's the template class chain:

template<std::size_t... Indexes>
class NonRecursiveClass
{
    public:

        void show(void)
        {
            print(Indexes...);
        }
};

template<std::size_t Count, std::size_t Index, std::size_t... Indexes>
class RecursiveClass;

template<std::size_t Count, std::size_t Index, std::size_t... Indexes>
class RecursiveClass : public RecursiveClass<Count - 1u, Indexes..., Index>
{
};

template<std::size_t Index, std::size_t... Indexes>
class RecursiveClass<0u, Index, Indexes...> : public NonRecursiveClass<Index, Indexes...>
{
};

Basically, the idea is that if you create, for instance, a RecursiveClass<5u, 10u, 1u, 6u, 478u, 23u> object, it will inherit from a NonRecursiveClass<23u, 478u, 6u, 1u, 10u> object and you have your std::size_t parameter sequence backward at compile time.

Unfortunately when I try it out, I still get the original order. Here's my main function:

int main(void)
{
    RecursiveClass<5u, 10u, 1u, 6u, 478u, 23u> foo;
    foo.show();
    return 0;
}

And here's the output:

10 1 6 478 23

What did I do wrong?

Barry
  • 286,269
  • 29
  • 621
  • 977
Pippin
  • 323
  • 1
  • 9

1 Answers1

2

What did I do wrong?

Think about what you're doing here:

template<std::size_t Count, std::size_t Index, std::size_t... Indexes>
class RecursiveClass : public RecursiveClass<Count - 1u, Indexes..., Index>

If you're not done yet (that is, if Count != 0), then what you do is you take the first one and move it to the back. Let's just follow through that algorithm:

RecursiveClass<5, 10, 1, 6, 478, 23>
└─ RecursiveClass<4, 1, 6, 478, 23, 10> // 10 to the back
   └─ RecursiveClass<3, 6, 478, 23, 10, 1> // 1 to the back
      └─ RecursiveClass<2, 478, 23, 10, 1, 6> // 6 to the back
         ...

We're not reversing the sequence. We're just rotating it one full rotation. That's why we end up printing the same thing.

What you need to do is pre-pend each element to a different sequence:

template <std::size_t...> struct sequence;

template <typename T, typename U>
class RecursiveClassImpl;

template <std::size_t I, std::size_t... Is, std::size_t... Js>
class RecursiveClassImpl<sequence<I, Is...>, sequence<Js...>>
    : public RecursiveClassImpl<sequence<Is...>, sequence<I, Js...>>
//                                               ^^^^^^^^^^^^^^^^^^
//                                               NB: prepend
{ };

template <std::size_t... Js>
class RecursiveClassImpl<sequence<>, sequence<Js...>>
    : public NonRecursiveClass<Js...>
{ };

template<std::size_t... Indexes>
class RecursiveClass : public RecursiveClassImpl<sequence<Indexes...>, sequence<>>
{ };
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Thank you very much sir. I don't know what I was thinking, really. May I ask why you chose to make `sequence` a `struct` rather than a `class`? Most examples I saw seem to prefer `struct` and I was wondering why that might be :) – Pippin May 13 '18 at 17:48
  • 2
    @Pippin Doesnt matter, it's not even a complete type. Metaprogramming tends to prefer `struct` because there isn't anything to encapsulate and it saves you having to type `public` everywhere. – Barry May 13 '18 at 19:27