0

I want to put a variable number of arguments into a buffer, and so I've overloaded the << operator to insert values into given buffer:

template<typename T, typename... Args>
void pack(T first, Args... args, std::vector<uint8_t> &buffer) {
    pack(args ..., buffer);
    buffer << first;
} 

void pack(std::vector<uint8_t> &buffer) { return; }

Since variadic template functions rely on recursion, my idea is to have a base case that returns the buffer and a recursive case that inserts the first argument into the buffer (after the recursive call).

However, if I run code like:

std::vector<uint8_t> buffer;
pack((uint8_t)0xFF, (uint32_t)0x0A, buffer);
hex_dump(buffer);

I get an error message saying:

In file included from main.cpp:2:0:
./misc.hpp:20:6: note: candidate: template<class T, class ... Args> void pack(T, Args ..., std::vector<unsigned char>&)
 void pack(T first, Args... args, std::vector<uint8_t> &buffer);
      ^~~~
./misc.hpp:20:6: note:   template argument deduction/substitution failed:
main.cpp:35:47: note:   candidate expects 2 arguments, 3 provided
     pack((uint8_t)0xFF, (uint32_t)0x0A, buffer);

How can I pass the buffer in the recursive case, so that I can append the value to partially filled buffer?

Shuzheng
  • 11,288
  • 20
  • 88
  • 186

1 Answers1

4

Simpler would be to have your buffer at first argument:

void pack(std::vector<uint8_t> &) {}

template<typename T, typename... Args>
void pack(std::vector<uint8_t> &buffer, T first, Args... args) {
    buffer << first;
    pack(buffer, args ...);
}

And in C++17, with Fold expression, you may directly write:

template<typename T, typename... Args>
void pack(std::vector<uint8_t> &buffer, Args... args) {
    (buffer << ... << args);
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Thanks, however, your solution gives the error "/tmp/ccNl3d0x.o: In function `main': main.cpp:(.text+0x267): undefined reference to `void pack(std::vector >&, unsigned char, unsigned int)' collect2: error: ld returned 1 exit status". Any idea? – Shuzheng Aug 21 '17 at 09:19
  • Where have you defined the template ? in a cpp (which is not where you use it ) ? – Jarod42 Aug 21 '17 at 09:21
  • I've the declared the template in a .hpp file which I include, but defined the template in a .cpp file - isn't this correct? – Shuzheng Aug 21 '17 at 09:22
  • I see that it works, if I take the template definition into the main.cpp file - but I don't want to define in every file, where I use this template? – Shuzheng Aug 21 '17 at 09:24
  • 3
    Look at [why-can-templates-only-be-implemented-in-the-header-file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – Jarod42 Aug 21 '17 at 09:25
  • thanks, I didn't knew this. I don't think that is elegant, but if that's the only way of doing it... – Shuzheng Aug 21 '17 at 09:33
  • @Shuzheng you could upvote and/or accept this answer instead of just saying "thanks". – YSC Aug 21 '17 at 09:37
  • @Jarod42 - is my solution of putting `inline` before both template definitions in the header file the correct solution? Your link mostly talk about template classes, and doesn't really mention much about the use of `inline`. – Shuzheng Aug 21 '17 at 09:43
  • template definitions are implicitly `inline`, so you can omit `inline` for template definitions. – Jarod42 Aug 21 '17 at 09:49