user27248672
user27248672

Reputation: 11

C++17 emplace_back a struct with a non trivial union in a vector

I have a struct containing a union with non trivial types:

struct union_struct {
    enum class type {integer, str} type;
    union {
        int i;
        std::string s;
    };

    union_struct(): type(type::integer) {
        i = 1;
    }

    ~union_struct() {
        switch (type) {
            case type::str:
                s.~string();
            case type::integer:
                break;
        }
    }
};

I have a vector containing this struct:

vector<union_struct> v;

I can successfully compile the code if I simply construct the struct yet if i try to call emplace_back on the vector compilation fails.

This compiles:

int main() {
    union_struct a(), *b = new union_struct();
    cout << a.i << endl;
    cout << b->i << endl;
}

Output:

1
1

This fails:

int main() {
    vector<union_struct> v;
    v.emplace_back();
}

Compiler output:

In file included from /usr/include/c++/9/vector:66,
                 from testfile.cpp:2:
/usr/include/c++/9/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<union_struct*>; _ForwardIterator = union_struct*]’:
/usr/include/c++/9/bits/stl_uninitialized.h:307:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<union_struct*>; _ForwardIterator = union_struct*; _Tp = union_struct]’
/usr/include/c++/9/bits/stl_uninitialized.h:329:2:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = union_struct*; _ForwardIterator = union_struct*; _Allocator = std::allocator<union_struct>]’
/usr/include/c++/9/bits/vector.tcc:474:3:   required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {int}; _Tp = union_struct; _Alloc = std::allocator<union_struct>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<union_struct*, std::vector<union_struct> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = union_struct*]’
/usr/include/c++/9/bits/vector.tcc:121:4:   required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int}; _Tp = union_struct; _Alloc = std::allocator<union_struct>; std::vector<_Tp, _Alloc>::reference = union_struct&]’
testfile.cpp:32:21:   required from here
/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
  127 |       static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
      |                                                                        ^~~~~

Upvotes: 0

Views: 52

Answers (0)

Related Questions