Search code examples
c++c++17variadic-templates

Parsing data via variadic templates


I have some code which does some serial communication with some hardware and then reads back some data (as as std::string).

  std::string data = cmd_exe("gmov");
  char cmdReadback[4];
  uint32_t Speed;
  uint8_t uSpeed;
  uint16_t Accel;
  uint16_t Decel;
  uint32_t AntiplaySpeed;
  uint8_t uAntiplaySpeed; 
  cpMemReadback(cmdReadback, data, 0);
  cpMemReadback(Speed, data, 4);
  cpMemReadback(uSpeed, data, 8);
  cpMemReadback(Accel, data, 9);
  cpMemReadback(Decel, data, 11);
  cpMemReadback(AntiplaySpeed, data, 13);
  cpMemReadback(uAntiplaySpeed, data, 17);

where cpMemReadback is quite trivial:

static constexpr auto cpMemReadback = [](auto& reg, std::string& s, size_t ix) {
  std::memcpy(&reg, s.data()+ix, sizeof(reg));
};

There are still some ugly things in this code - but what's bugging me most, is this useless call of cpMemReadback and then tracking of the index. I'd like to write:

parse_data(data, cmdReadback, Speed, uSpeed, ...);

I know that I'd want to use variadic templates, I presumably need a template parameter to track the index and then a parameter pack for my variables and then recursively execute the code, incrementing my index tracking template parameter. I'm just too stupid to actually write the code.


Solution

  • As I understand, you might have:

    template <typename... Ts>
    void parseData(const std::string& data, Ts&... args)
    {
        [[maybe_unused]]std::size_t idx = 0;
        ((cpMemReadback(args, data, idx), idx += sizeof (Ts)), ...);
    }
    

    and then replace

    cpMemReadback(cmdReadback, data, 0);
    cpMemReadback(Speed, data, 4);
    cpMemReadback(uSpeed, data, 8);
    cpMemReadback(Accel, data, 9);
    cpMemReadback(Decel, data, 11);
    cpMemReadback(AntiplaySpeed, data, 13);
    cpMemReadback(uAntiplaySpeed, data, 17);
    

    by

    parse_data(data,
               cmdReadback,
               Speed,
               uSpeed,
               Accel,
               Decel,
               AntiplaySpeed,
               uAntiplaySpeed);