Creating and storing string in a union inside a struct in a vector C++14 (Unrestricted Union)
Creating and storing string in a union inside a struct in a vector C++14 (Unrestricted Union)
Can anyone please explain how to assign and push a string(in a union inside a struct) into a vector? Is this possible? Is the vector trying to access invalid memory?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef struct
int height;
int width;
Page;
typedef struct varstruct
int test;
union uni
Page page;
int intVar;
string stringVar;
uni()
new (&stringVar) std::string();
~uni()
VarUnion;
varstruct()
~varstruct()
VariableDataStruct;
vector<VariableDataStruct> List;
int main()
VariableDataStruct structeg;
structeg.test = 1;
structeg.VarUnion.stringVar = "Test";
List.push_back(structeg);
cout<<structeg.VarUnion.stringVar<<endl;
structeg.VarUnion.stringVar.~basic_string();
return 0;
The code works fine in the absence "List.push_back(structeg);" statement. On addition of this statement gives the following errors:
In file included from /usr/include/c++/4.8.3/x86_64-redhat-linux/bits/c++allocator.h:33:0,
from /usr/include/c++/4.8.3/bits/allocator.h:46,
from /usr/include/c++/4.8.3/string:41,
from /usr/include/c++/4.8.3/bits/locale_classes.h:40,
from /usr/include/c++/4.8.3/bits/ios_base.h:41,
from /usr/include/c++/4.8.3/ios:42,
from /usr/include/c++/4.8.3/ostream:38,
from /usr/include/c++/4.8.3/iostream:39,
from unionstring2.cc:1:
/usr/include/c++/4.8.3/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = varstruct; _Args = const varstruct&; _Tp = varstruct]’:
/usr/include/c++/4.8.3/bits/alloc_traits.h:254:4: required from ‘static typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = varstruct; _Args = const varstruct&; _Alloc = std::allocator<varstruct>; typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type = void]’
/usr/include/c++/4.8.3/bits/alloc_traits.h:393:57: required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = varstruct; _Args = const varstruct&; _Alloc = std::allocator<varstruct>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.8.3/bits/stl_vector.h:906:34: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = varstruct; _Alloc = std::allocator<varstruct>; std::vector<_Tp, _Alloc>::value_type = varstruct]’
unionstring2.cc:34:28: required from here
/usr/include/c++/4.8.3/ext/new_allocator.h:120:4: error: use of deleted function ‘varstruct::varstruct(const varstruct&)’
::new((void *)__p) _Up(std::forward<_Args>(__args)...);
^
unionstring2.cc:12:16: note: ‘varstruct::varstruct(const varstruct&)’ is implicitly deleted because the default definition would be ill-formed:
typedef struct varstruct{
^
unionstring2.cc:12:16: error: use of deleted function ‘varstruct::uni::uni(const varstruct::uni&)’
unionstring2.cc:14:19: note: ‘varstruct::uni::uni(const varstruct::uni&)’ is implicitly deleted because the default definition would be ill-formed:
union uni{
^
unionstring2.cc:17:10: error: union member ‘varstruct::uni::stringVar’ with non-trivial ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’
string stringVar;
^
In file included from /usr/include/c++/4.8.3/vector:62:0,
from unionstring2.cc:3:
/usr/include/c++/4.8.3/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = varstruct; _Args = varstruct]’:
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<varstruct*>; _ForwardIterator = varstruct*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<varstruct*>; _ForwardIterator = varstruct*]’
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<varstruct*>; _ForwardIterator = varstruct*; _Tp = varstruct]’
/usr/include/c++/4.8.3/bits/stl_uninitialized.h:281:69: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = varstruct*; _ForwardIterator = varstruct*; _Allocator = std::allocator<varstruct>]’
/usr/include/c++/4.8.3/bits/vector.tcc:415:43: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = const varstruct&; _Tp = varstruct; _Alloc = std::allocator<varstruct>]’
/usr/include/c++/4.8.3/bits/stl_vector.h:911:27: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = varstruct; _Alloc = std::allocator<varstruct>; std::vector<_Tp, _Alloc>::value_type = varstruct]’
unionstring2.cc:34:28: required from here
/usr/include/c++/4.8.3/bits/stl_construct.h:75:7: error: use of deleted function ‘varstruct::varstruct(const varstruct&)’
::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...);
Is there any alternative?
std::vector<T>
T
1 Answer
1
One of members of your union is string
, according to reference
string
If a union contains a non-static data member with a non-trivial
special member function (copy/move constructor, copy/move assignment,
or destructor), that function is deleted by default in the union and
needs to be defined explicitly by the programmer.
so you cannot compile because during the call of vector::push_back
copy constructor of uni
is called, but this function is deleted. If you want to compile your code you need to add copy constructor:
vector::push_back
uni
uni(const uni& u)
new (&stringVar) std::stringu.stringVar;
then your code compiles and even works, but it is not good approach to use union with non-trivial types. You should add type
member to your struct to control which type of your union is active. Then you can delete in destructor the right member (call destructor for non-trivial types). Good example is presented in Bjarne Stroustrup book C++ Programming Language , chapter Anonymous Unions.
type
Modified version (it is not full code, only IDEA) of your code with type
member in struct:
type
enum TYPE INT,STR,PAGE;
typedef struct varstruct
int test;
union
Page page;
int intVar;
string stringVar;
;
void setPage (Page p)
if (type == STR)
stringVar.~string();
page = p;
type = PAGE;
void setInt (int i)
if (type == STR)
stringVar.~string();
intVar = i;
type = INT;
void setString (string s)
if (type == STR)
stringVar = s;
else
new (&stringVar) std::strings;
type = STR;
TYPE type = INT;
varstruct (const varstruct& v)
if (v.type == STR)
new (&stringVar) std::stringv.stringVar;
else if (v.type == INT)
intVar = v.intVar;
else if (v.type == PAGE)
page = v.page;
type = v.type;
varstruct()
~varstruct()
if (type == STR)
stringVar.~string();
VariableDataStruct;
and the code in main:
VariableDataStruct structeg;
structeg.test = 1;
structeg.setString("Test");
List.push_back(structeg);
cout<<structeg.stringVar<<endl;
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Your union has a default constructor, but not a copy constructor. It of course doesn't know which member is set, and so which member is supposed to be copied. On the other hand,
std::vector<T>
requiresT
to be copyable or at least movable.– Igor Tandetnik
Sep 13 '18 at 16:23