1

std::variant is a replacement of union.

But union can pass over network and receive in another platform(different compiler or arch) safely. Can std::variant do so?

For example, I have two machine A and B. A is windows, MSVC 19.4. B is Linux, gcc(or other compilers, such MSVC 17). I compile the code under A(or B):

std::variant<int, double> v = 1; // holds int.
f.write(&v, sizeof(v));

Can B read correct value using the following code from the same file?

std::variant<int, double> v;
f.read(&v, sizeof(v));

If std::variant couldn't pass over network safely. Are there any library provides one? boost::variant? or maybe to create a customize implemation that act like std::variant?

欢乐的Xiaox
  • 479
  • 4
  • 6
  • 6
    You shouldn't even pass an `int` over the network like that, let alone `std::variant`. Use a serialization library or serialize it yourself. – bolov Feb 24 '20 at 01:58
  • There is actually a good question hiding inside this one: whether a variant that contains only PODs is itself a POD. Rereading the (briefly short) definition of variant, it is silent on this subject matter, so I'll say it's unspecified. – Sam Varshavchik Feb 24 '20 at 02:08
  • @SamVarshavchik At least in C++20 it is, don't know whether it is considered defect report against C++17. Change results from [p0602r4](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0602r4.html). – walnut Feb 24 '20 at 02:39
  • @OP: Your code doesn't compile either, if `f` is a standard stream. You need to `reinterpret_cast` to `char*` explicitly to make this compile. – walnut Feb 24 '20 at 02:47

1 Answers1

5

In general, neither union, variant or many other types in C++ can be memory dumped into a file and then safely read.

When transferring data across multiple platforms (meaning hardware), many things can make the transfer unsafe:

  • Endianness (most machines today such as x86 are little endian)
  • Size (the int type you are referring to for example can be 4 bytes on one platform, 8 on another.)
  • How many bits a byte has (CHAR_BIT, usually 8, granted this only applies to few arcane platforms)
  • The floating point implementation used. (IEEE-754 is used by most hardware these days, but the C++ standard does not require this)

Because of this, the only safe way to transfer data cross-platform is to use a standardized intermediate data format, which is usually called serialization. Many libraries can help you with this. Some to look into are

If the question is more targeting the memory layout of std::variant, the same thing goes for std::variant as any other std container: the memory layout is implementation defined. (Implementation here means the standard library implementation used). For example, some standard library do a small string optimization in std::string, which can contain small strings (say, less than 32 characters) without heap allocations. Some don't. So then you have a very big difference in memory layout for the same type.

So either you guarantee that both sender and receiver have the same hardware and standard library implementation or you use a serialization library to ensure the same data arrives as what you sent.

Jan15
  • 499
  • 3
  • 11