C++ Vector of classes push back error - c++

I'm new in C++ , i use G++ compiler (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1
i try to implement undirected wieghted Graph. by two classes Edges and Graph. but the compiler gives me this error
the compiler gives this error
/usr/include/c++/4.8/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...)
[with _Up = UNDIR_W_EDGE; _Args = {const UNDIR_W_EDGE&}; _Tp =
UNDIR_W_EDGE]':
/usr/include/c++/4.8/bits/alloc_traits.h:254:4: required from 'static typename
std::enable_ifAlloc>::_construct_helper<_Tp,
_Args>::value, void>::type std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&&
...) [with _Tp = UNDIR_W_EDGE; _Args = {const UNDIR_W_EDGE&}; _Alloc =
std::allocator; typename
std::enable_ifAlloc>::_construct_helper<_Tp,
_Args>::value, void>::type = void]'
/usr/include/c++/4.8/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 = UNDIR_W_EDGE; _Args = {const UNDIR_W_EDGE&}; _Alloc =
std::allocator; decltype (_S_construct(__a, __p,
(forward<_Args>)(std::allocator_traits::construct::__args)...)) =
]'
/usr/include/c++/4.8/bits/stl_vector.h:906:34: required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp
= UNDIR_W_EDGE; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = UNDIR_W_EDGE]'
../src/GRAPH.h:31:5: required from 'void GRAPH::addEdge(const Edge&) [with Edge = UNDIR_W_EDGE]'
../src/main.cpp:32:13: required from here
/usr/include/c++/4.8/ext/new_allocator.h:120:4: error: no matching function for call to 'UNDIR_W_EDGE::UNDIR_W_EDGE(const UNDIR_W_EDGE&)'
{ ::new((void *)__p) _Up(std::forward<Args>(_args)...); }
The Code
GRAPH.h file
#include "vector"
template <typename Edge>
class GRAPH {
private:
// Implementation-dependent code
int Vcnt;
int Ecnt;
std::vector<std::vector< Edge > > adj;
public:
GRAPH(int x):Vcnt(x),Ecnt(0) {
adj.resize(Vcnt);
}
virtual ~GRAPH();
virtual int V() const;
virtual int E() const;
virtual void addEdge(const Edge &e){
adj[e.V()].push_back(e);
adj[e.W()].push_back(e);
Ecnt++;
};
virtual std::vector< Edge > adjIterator(int) const;
};
UNDIRWEDGE.h file
class UNDIR_W_EDGE {
int v,w;
float weight;
public:
UNDIR_W_EDGE(int v, int w, float weight);
UNDIR_W_EDGE(UNDIR_W_EDGE &);
virtual ~UNDIR_W_EDGE();
virtual int V()const;
virtual int W()const;
virtual float WEIGHT()const;
virtual int CompareTo(UNDIR_W_EDGE e)const;
};
in UNDIRWEDGE.cpp
inline int UNDIR_W_EDGE::CompareTo(UNDIR_W_EDGE e)const{
if(this->weight > e.weight) return 1;
else if (this->weight < e.weight)return -1;
else return 0;
}
in main.cpp
GRAPH<UNDIR_W_EDGE> g(10);
UNDIR_W_EDGE e(0,7,0.0);
g.addEdge(e);

You don't have a copy constructor for UNDIR_W_EDGE.
The copy constructor is required inside std::vector<UNDIR_W_EDGE>, as well as in CompareTo which takes its argument by value (for some reason).
You do have this:
UNDIR_W_EDGE(UNDIR_W_EDGE &);
Presumably you intended for it to be:
UNDIR_W_EDGE(const UNDIR_W_EDGE&);

Related

Create a std::vector of std::vectors of class without copy constructor

I want to create a std::vector<std::vector<LibraryClass>> where LibraryClass is not available to me for modifcation, and has no copy constructor.
For a std::vector<LibraryClass>, the following code compiles:
#include <vector>
class LibraryClass {
public:
LibraryClass() {};
LibraryClass(const LibraryClass&) = delete;
};
class MainClass {
public:
MainClass(int);
std::vector<LibraryClass> collection;
};
MainClass::MainClass(int nx)
: collection( nx ) {
}
int main() {
MainClass main_class(3);
}
But with a std::vector<std::vector<LibraryClass>>, it doesn't (use of deleted function - the copy constructor):
#include <vector>
class LibraryClass {
public:
LibraryClass() {};
LibraryClass(const LibraryClass&) = delete;
};
class MainClass {
public:
MainClass(int, int);
std::vector<std::vector<LibraryClass>> collection;
};
MainClass::MainClass(int nx, int ny)
: collection( nx, std::vector<LibraryClass>(ny) ) {
}
int main() {
MainClass main_class(3, 4);
}
What can I do to achieve this?
Thanks you in advance.
EDIT: After compiling with g++ -o test_vec_of_ves test_vec_of_vecs.cpp the exact error is :
In file included from /usr/include/c++/7/vector:62:0,
from test_vec_of_vecs.cpp:1:
/usr/include/c++/7/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = LibraryClass; _Args = {const LibraryClass&}]’:
/usr/include/c++/7/bits/stl_uninitialized.h:83:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const LibraryClass*, std::vector<LibraryClass> >; _ForwardIterator = LibraryClass*; bool _TrivialValueTypes = false]’
/usr/include/c++/7/bits/stl_uninitialized.h:134:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const LibraryClass*, std::vector<LibraryClass> >; _ForwardIterator = LibraryClass*]’
/usr/include/c++/7/bits/stl_uninitialized.h:289:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const LibraryClass*, std::vector<LibraryClass> >; _ForwardIterator = LibraryClass*; _Tp = LibraryClass]’
/usr/include/c++/7/bits/stl_vector.h:331:31: required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = LibraryClass; _Alloc = std::allocator<LibraryClass>]’
/usr/include/c++/7/bits/stl_construct.h:75:7: required from ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::vector<LibraryClass>; _Args = {const std::vector<LibraryClass, std::allocator<LibraryClass> >&}]’
/usr/include/c++/7/bits/stl_uninitialized.h:210:18: required from ‘static _ForwardIterator std::__uninitialized_fill_n<_TrivialValueType>::__uninit_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = std::vector<LibraryClass>*; _Size = long unsigned int; _Tp = std::vector<LibraryClass>; bool _TrivialValueType = false]’
/usr/include/c++/7/bits/stl_uninitialized.h:255:17: required from ‘_ForwardIterator std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = std::vector<LibraryClass>*; _Size = long unsigned int; _Tp = std::vector<LibraryClass>]’
/usr/include/c++/7/bits/stl_uninitialized.h:366:39: required from ‘_ForwardIterator std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, std::allocator<_Tp2>&) [with _ForwardIterator = std::vector<LibraryClass>*; _Size = long unsigned int; _Tp = std::vector<LibraryClass>; _Tp2 = std::vector<LibraryClass>]’
/usr/include/c++/7/bits/stl_vector.h:1342:33: required from ‘void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = std::vector<LibraryClass>; _Alloc = std::allocator<std::vector<LibraryClass> >; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::vector<LibraryClass>]’
/usr/include/c++/7/bits/stl_vector.h:298:27: required from ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::vector<LibraryClass>; _Alloc = std::allocator<std::vector<LibraryClass> >; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::vector<LibraryClass>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::vector<LibraryClass> >]’
test_vec_of_vecs.cpp:17:49: required from here
/usr/include/c++/7/bits/stl_construct.h:75:7: error: use of deleted function ‘LibraryClass::LibraryClass(const LibraryClass&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test_vec_of_vecs.cpp:6:3: note: declared here
LibraryClass(const LibraryClass&) = delete;
^~~~~~~~~~~~
Following underscore_d's advice, here is a version that appears to work (including some function that shows that something is done).
#include <vector>
#include <iostream>
#include <memory>
class LibraryClass {
public:
LibraryClass() {};
LibraryClass(const LibraryClass&) = delete;
void init(int aa, int bb) { a = aa; b = bb; };
void report() { std::cout << "I am " << a << " / " << b << std::endl; };
private:
int a, b;
};
class MainClass {
public:
MainClass(int, int);
void init();
void report();
std::vector<std::vector<std::unique_ptr<LibraryClass>>> collection;
};
MainClass::MainClass(int nx, int ny) {
collection.resize(nx);
for (int i=0; i<nx; ++i) {
collection[i].resize(ny);
for (int j=0; j<ny; ++j) {
collection[i][j] = std::make_unique<LibraryClass>();
}
}
}
void MainClass::init() {
for (int i=0; i<collection.size(); ++i) {
for (int j=0; j<collection[i].size(); ++j) {
collection[i][j]->init(i,j);
}
}
}
void MainClass::report() {
for (int i=0; i<collection.size(); ++i) {
for (int j=0; j< collection[i].size(); ++j) {
collection[i][j]->report();
}
}
}
int main() {
int nx = 3;
int ny = 4;
MainClass main_class(nx, ny);
main_class.init();
main_class.report();
}

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?
One of members of your union is string, according to reference
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:
uni(const uni& u) {
new (&stringVar) std::string{u.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.
Modified version (it is not full code, only IDEA) of your code with type member in struct:
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::string{s};
type = STR;
}
TYPE type = INT;
varstruct (const varstruct& v) {
if (v.type == STR)
new (&stringVar) std::string{v.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;

Reference to vector element in allocator aware class calls copy constructor

I have a class that contains a vector of vector. It is allocator aware. When trying to call the operator[] to store elements in a reference, Visual Studio 2015 fails to compile, AppleClang (latest) is fine with it.
I am unsure whether this is a bug or not, which compiler is right, or if there is some undefined behaviour somewhere in my code.
Here is a concise example, with everything as simple as possible.
#include <cstdlib>
#include <memory>
#include <new>
#include <vector>
/* Allocator */
template <class T>
struct my_allocator {
typedef T value_type;
my_allocator() = default;
template <class U>
constexpr my_allocator(const my_allocator<U>&) noexcept {
}
T* allocate(std::size_t n) {
if (n > std::size_t(-1) / sizeof(T))
throw std::bad_alloc();
if (auto p = static_cast<T*>(std::malloc(n * sizeof(T))))
return p;
throw std::bad_alloc();
}
void deallocate(T* p, std::size_t) noexcept {
std::free(p);
}
};
template <class T, class U>
bool operator==(const my_allocator<T>&, const my_allocator<U>&) {
return true;
}
template <class T, class U>
bool operator!=(const my_allocator<T>&, const my_allocator<U>&) {
return false;
}
/* Example Element */
struct X {
X() = default;
X(X&&) = default;
X& operator=(X&&) = default;
X(const X&) = delete;
X& operator=(const X&) = delete;
int test = 42;
};
/* Example Container Class */
template <class T, class Allocator = std::allocator<T>>
struct vec_of_vec {
using OuterAlloc = typename std::allocator_traits<
Allocator>::template rebind_alloc<std::vector<T, Allocator>>;
vec_of_vec(const Allocator& alloc = Allocator{})
: data(10, std::vector<T, Allocator>{ alloc },
OuterAlloc{ alloc }) {
for (int i = 0; i < 10; ++i) {
data[i].resize(42);
}
}
std::vector<T, Allocator>& operator[](size_t i) {
return data[i];
}
std::vector<std::vector<T, Allocator>, OuterAlloc> data;
};
/* Trigger Error */
int main(int, char**) {
my_allocator<X> alloc;
vec_of_vec<X, my_allocator<X>> test(alloc);
X& ref_test = test[0][0]; // <-- Error Here!
printf("%d\n", ref_test.test);
return 0;
}
VS tries to use the copy constructor of X.
error C2280: 'X::X(const X &)': attempting to reference a deleted function
function main.cpp(42): note: see declaration of 'X::X'
Is there something I am missing with the use of allocators and allocator_traits?
GCC error sheds light on what's going on, potentially same in VS2015 case.
In file included from memory:65,
from prog.cc:2:
bits/stl_uninitialized.h: In instantiation of '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = __gnu_cxx::__normal_iterator<const X*, std::vector<X, my_allocator<X> > >; _ForwardIterator = X*; _Allocator = my_allocator<X>]':
bits/stl_vector.h:454:31: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = X; _Alloc = my_allocator<X>]'
bits/alloc_traits.h:250:4: required from 'static std::_Require<std::__and_<std::__not_<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type>, std::is_constructible<_Tp, _Args ...> > > std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::vector<X, my_allocator<X> >; _Args = {const std::vector<X, my_allocator<X> >&}; _Alloc = my_allocator<std::vector<X, my_allocator<X> > >; std::_Require<std::__and_<std::__not_<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type>, std::is_constructible<_Tp, _Args ...> > > = void]'
bits/alloc_traits.h:344:16: required from 'static decltype (std::allocator_traits<_Alloc>::_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::vector<X, my_allocator<X> >; _Args = {const std::vector<X, my_allocator<X> >&}; _Alloc = my_allocator<std::vector<X, my_allocator<X> > >; decltype (std::allocator_traits<_Alloc>::_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = void]'
bits/stl_uninitialized.h:351:25: required from '_ForwardIterator std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, _Allocator&) [with _ForwardIterator = std::vector<X, my_allocator<X> >*; _Size = long unsigned int; _Tp = std::vector<X, my_allocator<X> >; _Allocator = my_allocator<std::vector<X, my_allocator<X> > >]'
bits/stl_vector.h:1466:33: required from 'void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = std::vector<X, my_allocator<X> >; _Alloc = my_allocator<std::vector<X, my_allocator<X> > >; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::vector<X, my_allocator<X> >]'
bits/stl_vector.h:421:9: required from 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = std::vector<X, my_allocator<X> >; _Alloc = my_allocator<std::vector<X, my_allocator<X> > >; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = std::vector<X, my_allocator<X> >; std::vector<_Tp, _Alloc>::allocator_type = my_allocator<std::vector<X, my_allocator<X> > >]'
prog.cc:59:42: required from 'vec_of_vec<T, Allocator>::vec_of_vec(const Allocator&) [with T = X; Allocator = my_allocator<X>]'
prog.cc:76:46: required from here
bits/stl_uninitialized.h:275:25: error: no matching function for call to '__gnu_cxx::__alloc_traits<my_allocator<X>, X>::construct(my_allocator<X>&, X*, const X&)'
__traits::construct(__alloc, std::__addressof(*__cur), *__first);```
Wandbox
if we go from bottom to top we see:
vec_of_vec constructor
filling vector<vector> by 10 copies of empty inner vector
construction of copies
Despite of the fact that inner vector is empty, its copy constructor requires that the type it contains is copy-constructible.
P.S.
I don't know how clang overcomes this. Potentially it recognises that vector<vector> if filled with default value (if constructor with passed allocator instance still qualifies as default) and so instead of copying uses default construction
EDIT:
To fix the error replace
vec_of_vec(const Allocator& alloc = Allocator{})
: data(10, std::vector<T, Allocator>{ alloc },
OuterAlloc{ alloc }) {
for (int i = 0; i < 10; ++i) {
data[i].resize(42);
}
}
by
vec_of_vec(const Allocator& alloc = Allocator{})
{
data.resize(10); // here we don't `fill` it by copies but default-construct 10 instances
for (int i = 0; i < 10; ++i) {
data[i].resize(42);
}
}
or version for stateful allocator:
vec_of_vec(const Allocator& alloc = Allocator{}):
data(OuterAlloc(alloc))
{
for (int i = 0; i < 10; ++i) {
data.emplace_back(alloc);
data.back().resize(42);
}
}

Passing a function and arguments to a thread

Problem Statement - tl;dr
Add numbers to a vector, then output them
Details
My intention was to make a class Foo, that contained a std::vector<int> that I could populate in a thread-safe manner. I created an AddValue method to allow adding values to that vector keeping thread-safety in mind.
std::mutex mt;
class Foo
{
public:
void AddValue(int i)
{
std::lock_guard<std::mutex> lg{ mt };
values.push_back(i);
}
void PrintValues() const
{
for (int i : values)
{
std::cout << i << " ";
}
}
private:
std::vector<int> values;
};
I then made a free function that I could use to create a thread, without any knowledge of the internals of Foo.
void Func(Foo& foo, int t)
{
for (int i = 0; i < t; i++)
{
foo.AddValue(i);
}
}
My intention was to add the following values to the vector (in whatever order they ended up due to the thread timing)
{3, 2, 2, 1, 1, 1, 0, 0, 0, 0}
Here is a quick test to see if that was working.
int main()
{
Foo foo;
std::vector<std::thread> threads;
for (int i = 1; i < 5; ++i)
{
threads.emplace_back(Func, foo, i);
}
std::for_each(begin(threads), end(threads), [](std::thread& t){ t.join(); });
foo.PrintValues();
}
Problem
The above code won't compile
This is the error message
In file included from /usr/include/c++/4.9/mutex:42:0,
from 3:
/usr/include/c++/4.9/functional: In instantiation of 'struct std::_Bind_simple<void (*(Foo, int))(Foo&, int)>':
/usr/include/c++/4.9/thread:140:47: required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(Foo&, int); _Args = {Foo&, int&}]'
/usr/include/c++/4.9/ext/new_allocator.h:120:4: required from 'void __gnu_cxx::new_allocator< <template-parameter-1-1> >::construct(_Up*, _Args&& ...) [with _Up = std::thread; _Args = {void (&)(Foo&, int), Foo&, int&}; _Tp = std::thread]'
/usr/include/c++/4.9/bits/alloc_traits.h:253:4: required from 'static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::thread; _Args = {void (&)(Foo&, int), Foo&, int&}; _Alloc = std::allocator<std::thread>; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]'
/usr/include/c++/4.9/bits/alloc_traits.h:399: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 = std::thread; _Args = {void (&)(Foo&, int), Foo&, int&}; _Alloc = std::allocator<std::thread>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]'
/usr/include/c++/4.9/bits/vector.tcc:97:40: required from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {void (&)(Foo&, int), Foo&, int&}; _Tp = std::thread; _Alloc = std::allocator<std::thread>]'
44:42: required from here
/usr/include/c++/4.9/functional:1665:61: error: no type named 'type' in 'class std::result_of<void (*(Foo, int))(Foo&, int)>'
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
/usr/include/c++/4.9/functional:1695:9: error: no type named 'type' in 'class std::result_of<void (*(Foo, int))(Foo&, int)>'
_M_invoke(_Index_tuple<_Indices...>)
^
I don't quite understand that error message. Am I not adding the threads to the vector threads correctly?
You have to wrap the foo in a std::ref. Threads don't allow things to be passed by reference without that wrapper.

How can I get this code involving unique_ptr to compile?

#include <vector>
#include <memory>
using namespace std;
class A {
public:
A(): i(new int) {}
A(A const& a) = delete;
A(A &&a): i(move(a.i)) {}
unique_ptr<int> i;
};
class AGroup {
public:
void AddA(A &&a) { a_.emplace_back(move(a)); }
vector<A> a_;
};
int main() {
AGroup ag;
ag.AddA(A());
return 0;
}
does not compile... (says that unique_ptr's copy constructor is deleted)
I tried replacing move with forward. Not sure if I did it right, but it didn't work for me.
[~/nn/src] g++ a.cc -o a -std=c++0x
/opt/local/include/gcc44/c++/bits/unique_ptr.h: In member function 'A& A::operator=(const A&)':
a.cc:6: instantiated from 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = A, _Tp = A, _Alloc = std::allocator<A>]'
/opt/local/include/gcc44/c++/bits/vector.tcc:100: instantiated from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = A, _Tp = A, _Alloc = std::allocator<A>]'
a.cc:17: instantiated from here
/opt/local/include/gcc44/c++/bits/unique_ptr.h:219: error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>& std::unique_ptr<_Tp, _Tp_Deleter>::operator=(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_Deleter = std::default_delete<int>]'
a.cc:6: error: used here
In file included from /opt/local/include/gcc44/c++/vector:69,
from a.cc:1:
/opt/local/include/gcc44/c++/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = A, _Tp = A, _Alloc = std::allocator<A>]':
/opt/local/include/gcc44/c++/bits/vector.tcc:100: instantiated from 'void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = A, _Tp = A, _Alloc = std::allocator<A>]'
a.cc:17: instantiated from here
/opt/local/include/gcc44/c++/bits/vector.tcc:314: note: synthesized method 'A& A::operator=(const A&)' first required here
Probably your standard library doesn't (yet) define unique_ptr<T>::unique_ptr(unique_ptr &&). I checked my headers in 4.5 and it's there, so maybe try upgrading.
When it fails to find the move constructor, it would look for the copy constructor and find it deleted.
I get other errors when I compile that, though.
EDIT: Got it to work. I don't understand why you have to move an object which is already an rvalue reference, but you do. The only problem was a missing assigment operator.
#include <vector>
#include <memory>
using namespace std;
class A {
public:
A(): i(new int) {}
A(A const& a) = delete;
A &operator=(A const &) = delete;
A(A &&a): i(move(a.i)) {}
A &operator=(A &&a ) { i = move(a.i); }
unique_ptr<int> i;
};
class AGroup {
public:
void AddA(A &&a) { a_.emplace_back(move(a)); }
vector<A> a_;
};
int main() {
AGroup ag;
ag.AddA(A());
return 0;
}