Expanding a parameter pack while decreasing a variable

Feb 4, 2017 at 3:26pm
I'm stuck trying to decrease a value while expanding a parameter pack.
This is the best pseudo-code I could come up with.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <typeinfo>

template <typename ... Args>
void DisplayAll(Args ... args)
{
    std::cout << "Starting display." << std::endl;
    for(const auto& arg : {args...})
    {
        std::cout << arg << std::endl;
    }
    std::cout << "Display finished." << std::endl;
}

template <typename T>
std::string CreateArgument(int index)
{
    return std::to_string(index);
}

template <typename ... Args>
void RunTest(int StartIndex)
{
    DisplayAll(CreateArgument<Args>(StartIndex--)...);
}

int main(int argc, char *argv[])
{
    RunTest<std::string, std::string, std::string>(3);
    return 0;
}


The code shows 1, 2, 3 and (correctly) warns me about possibly invalid sequence point.
I want it to *reliably* show 3, 2, 1, but I don't know how.
Last edited on Feb 4, 2017 at 3:27pm
Feb 4, 2017 at 4:57pm
Seems like a good place to determine the "index" of arguments would be inside the DisplayAll function.
Feb 4, 2017 at 6:54pm
DisplayAll cannot change :(
Also, CreateArgument will not return the arg's index.
Feb 5, 2017 at 5:15am
It's unclear what exactly you want. Your statement
DisplayAll cannot change

Indicates there's some requirements you didn't share.

Is this acceptable? You were very close.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# include <iostream>
template <typename T>
std::string CreateArgument(int index) {
  return std::to_string(index);
}

template <typename... Args>
void RunTest(int start) {
  using left_to_right = int[];
  std::cout << "Starting display.\n";
  (void) left_to_right{0, (std::cout << (CreateArgument<Args>(start--)) << "\n", 0)...};
  std::cout << "Display finished.\n";
}

int main () {
  RunTest<std::string, std::string, std::string>(3);
}

http://rextester.com/EJXY16073

Last edited on Feb 5, 2017 at 5:59am
Feb 8, 2017 at 8:57pm
I'm quite sure start-- there brings me back to the starting point (invalid sequence point).
I've been able to work around this using compile-time lists and obscure stuff... altough I had to rework a lot of stuff to make it work.

This: http://stackoverflow.com/questions/15036063/obtain-argument-index-while-unpacking-argument-list-with-variadic-templates
Last edited on Feb 8, 2017 at 9:00pm
Feb 8, 2017 at 10:41pm
m quite sure start-- there brings me back to the starting point (invalid sequence point).

not in mbozzi's example

If your compiler is modern enough, you can replace that left-to-right array init hack with a fold expression:

1
2
3
4
5
6
template <typename... Args>
void RunTest(int start) {
  std::cout << "Starting display.\n";
  ((std::cout << CreateArgument<Args>(start--) << "\n"), ...);
  std::cout << "Display finished.\n";
}

Feb 8, 2017 at 11:03pm
Topic archived. No new replies allowed.