2

So, I have json file which has some parameters defining the name, value and type. for e.g., { name: "something", type: "uint32_t", value: 12 }

and I am creating struct mapping of this json parameter, it looks like

enum some_enum{en_int8, en_int16, ....};
struct{
  std::string name; // Name of parameter
  some_enum type;   // type of parameter
  union{
    uint8_t var1;
    uint16_t var2;
    ..... //all other requried types
  }
}

As I don't know about the type of parameter coming from file, I am creating this union for storing value and using enum to access the specified value.

I think this is c-style way to do it.

So, I want to ask, is there any alternative way, rather than of using union for creating mapping like this in C++/Modern C++. Thank you in advance.

lkopi
  • 21
  • 4
  • 4
    Yes `std::variant` is the alternative. – john Sep 06 '22 at 08:08
  • Since [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant) is already a discriminated union, you probably don't need the enum either. – Useless Sep 06 '22 at 08:19

3 Answers3

0

You can use std::variant but it is available and referenced officially from C++ 17. There is an alternative: Boost.Variant. As it is explained here: Boost Variant essentially a Union in c/c++? it provides a replacement for the generic C union in Boost library, but the underlying code does not implement the same behaviour, preferring aligned storage. Thus, it depends if you are constrained with strictly the same behaviour as a generic C union, or not. However, Boost.Variant requires a few additional efforts for templatizing your code, and/or writing functors to handle non-trivial argument types.

Andrei Vukolov
  • 118
  • 1
  • 10
0

Based on what you have described in the Q, I think you do not need to use union if you go for modern C++ features like std::any. So, I propose to use std::any like this instead of std::variant:

struct Param
{
  std::string name; // Name of the parameter
  std::any value;   // type and value of the parameter
}

and for using this struct:

   Param pi{"pi", std::make_any<double>(3.1415)};

In this case, the value member of your struct stores both your type and the value of the parameter.

Note: std::any is available since C++17. If you cannot migrate to C++17, you can use boost::any instead.

TonySalimi
  • 8,257
  • 4
  • 33
  • 62
  • 1
    std::any did not help as it did not give you access to the stored type. You have to know the type to access std::any and it protects you for wrong type access. But it looks that OP wants to store the type as it comes from the file. As this std::variant is much better fit I believe – Klaus Sep 06 '22 at 10:37
  • @Klaus but we can use `.type()` for variables of type `std::any` to access its `typeid`, no? To me, `std::any` keeps the value and the type (typeid) of a variable and is a better fit for this case. – TonySalimi Sep 06 '22 at 11:08
0

What you are trying to do seems to be a serialization task. You can write your own code for doing that, but there are several libraries what you can use instead: Oops (https://bitbucket.org/barczpe/oops), boost serialization (https://www.boost.org/doc/libs/1_80_0/libs/serialization/doc/index.html), or Cereal.