Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Using std::string and int inside the union

Is it correct to use std::string (or other non trivial types) with int (or other trivial and non trivial types) inside the same union?

I am already implemented it like this:

#include <iostream>
#include <string>

struct Foo
{
    enum Type {data_string, data_int};
    int m_type;
    
    Foo(Type t) : m_type(t)
    {
        if (t == Type::data_string) {
            new (&s) std::string();
        }
    }

    ~Foo()  
    {
        if (m_type == Type::data_string) {
            s.~basic_string();
        }
    }
    
    union
    {
        int n;
        std::string s;
    };
};

int main()
{
    Foo f1(Foo::Type::data_string);
    f1.s = "hello ";
    std::cout << f1.s;
    
    Foo f2(Foo::Type::data_int);
    f2.n = 100;
    std::cout << f2.n;
} 

and it works pretty good. But i am not sure about this code. Is it correct code from the C++ standard perspective?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You should not use a union with non trivial types.
A union is not meant to deal with proper construction and detruction of C++ objects in it.

You took care of it manually in your code, which is technically correct, but very much error prone. You can easily get into UB land if you construct or destruct the wrong type in the union.

In general in C++ is it advised to use std::variant for a generic sum-type / discriminated union (requires #include <variant>).

From the documentation:

The class template std::variant represents a type-safe union.

So instead of your union I recommend to use something like:

std::variant<int, std::string> m_value;

This way your Foo constructor and destructor can be defaulted. The variant will take care of proper construction and destruction of the std::string (or any other non-trivial type in it).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading