mardi 31 octobre 2017

Factory function for initialization of static const struct with array and lambda

I have a structure that should be statically initialized.

struct Option
{ char Option[8];
  void (*Handler)(const char* value);
};

void ParseInto(const char* value, const char** target); // string option
void ParseInto(const char* value, int* target, int min, int max); // int option

static int count = 1;
static const char* name;

static const Option OptionMap[] =
{ { "count", [](const char* value) { ParseInto(value, &count, 1, 100); } }
, { "name",  [](const char* value) { ParseInto(value, &name); } }
  // ...
};

Up to this point it works.

To get rid of repeating the lambda function definition over and over (there are dozens) I want to use a factory like this:

struct Option
{ const char Option[8];
  const void (*Handler)(const char* value);
  template<typename ...A>
  Option(const char (&option)[8], A... args)
  : Option(option)
  , Handler([args...](const char* value) { ParseInto(value, args...); })
  {}
};

static const Option OptionMap[] =
{ { "count", &count, 1, 100 }
, { "name",  &name }
};

This does not work for two reasons:

  1. I did not find a type for the first constructor parameter option that perfectly forwards the initialization of the character array. The difficult part is that the length of the assigned array does not match the array length in general.
  2. The even harder part is that the lambda function has a closure and therefore cannot decay to a function pointer. But all parameters are compile time constants. So It should be possible to make the constructor constexpr. However, lambdas seem not to support constexpr at all.

Anyone an idea how to solve this challenge?

The current work around is a variadic macro. Not that pretty, but of course, it works.

Context is C++11. I would not like to upgrade for now, but nevertheless a solution with a newer standard would be appreciated. Problems like this tend to reappear from time to time.

There are some further restrictions by the underlying (old) code. struct Option must be a POD type and the first member must be the character array so a cast from Option* to const char* is valid.

Aucun commentaire:

Enregistrer un commentaire