1
struct variant
{
    union variants
    {
        std::string s;
        int i;
        uint8_t none;
        variants() : none(0){}
        variants(const std::string & s) : s(s){} // option A
        ~variants(){}
    };

    enum class Tag {STR,INT,NONE};

    variant() = default;

    variant(const std::string & s)
        : tag(Tag::STR), v(s) // option A
    {
        // new (&v.s) std::string(s);  // option B
    }

    variant(const int i)
        : tag(Tag::INT)
    {
        v.i = i;
    }

    ~variant()
    {
        if (tag == Tag::STR)
        {
            using namespace std;
            v.s.~string();
        }
    }
    variants v;
    Tag tag = Tag::NONE;
};

is it undefined behavior to have a constructor in the union that directly constructs a certain member (with non trivial special member functions) as in option A in the code snippet above or must one always use the placement new operator as in option B?

Edit: Not sure how or where does the suggested duplicate fits? I'm asking about strictly adding a constructor to the union definition itself (please check the comments 'option A' in the code snippet)

Edit: The answer to my question is in the second duplicate not the first one (Do unrestricted unions require placement new and a constructor definition?)

mkmostafa
  • 3,071
  • 2
  • 18
  • 47
  • @Quentin could you please point me to the comment/answer that answers my question of adding a constructor to the non-anonymous union – mkmostafa Apr 09 '18 at 09:29
  • The accepted answer there outlines exactly how mem-init-lists work for unions, which seems to be what you're asking about. – Quentin Apr 09 '18 at 09:48
  • not exactly, the first difference is that my union is not anonymous. Second I'm asking about the possibility of defining a constructor inside the union *not about initializing a member of a union directly in the mem init list of the class encapsulating the union*. Not sure if these differences matter, hence I asked. – mkmostafa Apr 09 '18 at 17:31

0 Answers0