Home > Net >  C compile-time non-intrusive struct to tuple (or any another) class conversion
C compile-time non-intrusive struct to tuple (or any another) class conversion

Time:03-21

Prerequisites:
I have no access to boost.
Im have third-party C header, what describes structs, like

typedef struct
{
   int int_value;
   char char_value;
   bool bool_value;
}
example_struct_t;

I cant make any changes in it.

Target:
I need to serialize data from this structs in custom text format.

I have planned, to make by-type serializers, like SerializerBase, SerializerINT::SerializerBase, SerializerCHAR::SerializerBase and etc.

And use it in some template class, (pseudocode):

Serializer<example_struct_t = T>
{
   foreach_field_in<T> is field
   {
      if(field.type == typeof(int))
      {
         AddToResult(SerializerINT::Serialize(field.value));
      }
   }
}

Or something less "templated" (pseudocode):

class SerializationSequence<example_struct_t = T>
{
   std::vector<SerializerBase> sequence;

   SerializationSequence()
   {
       sequence = GenerateMethodsSequenceForThisStruct<T>(); // Compile time
   }
}

Does C has any way to parse this structs in compile time and making something, like std::tuple<int,char,bool>?

CodePudding user response:

C reflection proposal does this easy. It isn't in C yet.

There are various ways you can get at C parse trees. It is pretty extreme and involves hacking or using a custom compiler.

Finally, there are some hacks involving detecting airity of brace construction and unpacking with []s. This might be the most practical.

The basic idea is you can test, in an immeditate context, if T{a0, a1, a2} is legal. You make a type that has a "universal" template<class T>operator T(), and find the largest count of those you can make an instance of your type from using {}s.

Then you unpack via

auto&& [b0, b1, b2] = t;
return std::make_tuple(b0,b1,b2);

and extract the types from the resulting tuple, with a custom ("hand" written) version for each count.

It requires a bunch of code generation, has a max airity it handles, it only handles POD types well (with some extensions). But that technique is the closest you can get in current C .

Here is someone using this approach. I have no idea if they did it well, the license they used, etc; it is just an example of someone else doing this technique.

CodePudding user response:

The OP wrote that using boost is not possible, but then noted that the inclusion of a single header is possible. magic_get aka boost.pfr is a 1 header library, and should do exactly what the OP wants: turning a simple struct into a tuple. See github.com/apolukhin/magic_get

  • Related