Is there any alternative of using union in C++, if data type of variable is not specified

Viewed 112

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.

3 Answers

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.

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.

Related