I'm trying to do something like this:
#include <thread>
#include <vector>
void foo(bool &check){
}
int main(){
std::vector<bool> vec(1);
std::thread T(foo, std::ref(vec[0]));
}
Unfortunately gcc throws an error:
prog.cpp: In function 'int main()':
prog.cpp:10:34: error: use of deleted function 'void std::ref(const _Tp&&) [with _Tp = std::_Bit_reference]'
std::thread(foo, std::ref(vec[1]))
^
In file included from /usr/include/c++/4.9/thread:39:0,
from prog.cpp:1:
/usr/include/c++/4.9/functional:453:10: note: declared here
void ref(const _Tp&&) = delete;
However it works with a normal variable:
bool var;
std::thread(foo, std::ref(var));
I have no idea why I can't pass a reference to the vec element. Can someone explain why? Is there any workaround?
Problem is, that you use std::vector<bool>. operator [] for vector<bool> returns not bool, but std::vector<bool>::reference, that is proxy class.
You can use something like:
bool value = vec[0];
std::thread T(foo, std::ref(value));
T.join();
vec[0] = value;
Another workaround (not tested)
#include <thread>
#include <vector>
void foo(vector& v){
//here access v[0] and assign whatever value you'd like
//ideally you could pass an index as well
// if you want to access the Nth element
}
int main(){
std::vector<bool> vec(1);
std::thread T(foo, std::ref(vec));
}
Related
I have a program that is compute intensive that I would like to multithread. Here is the code:
#include <iostream>
#include <math.h>
#include <thread>
#include "print_binary.h"
#include "bit_at.h"
bool process(unsigned int start, unsigned int end) {
for (unsigned int i = 0; i < (sizeof(unsigned int)*8); i++)
{
for (unsigned int j = start; j < end; j++)
{
bit_at(i, j);
}
}
return true;
}
int main() {
unsigned int start {5000};
unsigned int end {11000};
std::thread thread_1 (process(start, end));
thread_1.join();
return 0;
}
When I attempt to compile this using g++20 on my M1 Mac, I get this error:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/thread:286:5: error: attempt to use a deleted function
_VSTD::__invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__config:856:15: note: expanded from macro '_VSTD'
#define _VSTD std::_LIBCPP_ABI_NAMESPACE
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/thread:297:12: note: in instantiation of function template specialization 'std::__thread_execute<std::unique_ptr<std::__thread_struct>, bool>' requested here
_VSTD::__thread_execute(*__p.get(), _Index());
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/thread:313:54: note: in instantiation of function template specialization 'std::__thread_proxy<std::tuple<std::unique_ptr<std::__thread_struct>, bool>>' requested here
int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
^
and_threaded.cpp:23:17: note: in instantiation of function template specialization 'std::thread::thread<bool, void>' requested here
std::thread thread_1 (process(start, end));
^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/type_traits:1916:5: note: '~__nat' has been explicitly marked deleted here
~__nat() = delete;
^
1 error generated.
Could someone explain to me what exactly error: attempt to use a deleted function means? My understanding is that std::thread converts the arguments passed to the function as rvalues, but the process() function should accept that. I have tried passing rvalues to process() like: std::thread thread_1(process(0, 5000)), as well as using rvalue references in the argument list of the function declaration. It all gives me the same error. I have also tried passing by reference using std::ref(start).
Any help at all is greatly appreciated.
process(start, end) calls the function process. And you pass the bool result to the std::thread constructor as a thread function.
You want to pass a pointer to the function itself, and its arguments, as separate arguments to the std::thread constructor:
std::thread thread_1 (&process, start, end);
I'm currently working on a project in C++ in which I have a list of structs stored in a vector that have a lot processing associated with them. In order to speed things up, I've chosen to split the program across multiple threads, and the lazy way I've chosen to do this is by adding a mutex to each struct in the standard library vector. This way I can have a number of threads iterate over the array and basically take ownership of the individual elements by calling mutex.try_lock(), and either completing the associated processing with that element, or moving onto the next open one.
Before we get started, note that the following actually does work.
#include <mutex>
#include <vector>
struct foo {
int a;
std::mutex b;
};
void working_demo () {
// assign by initializer list
foo f = {.a = 1};
}
int main () {
working_demo();
}
So, I intend to populate my standard vector in a way very similar to above, and it doesn't work.
#include <mutex>
#include <vector>
struct foo {
int a;
std::mutex b;
};
void broken_demo () {
std::vector<foo> bar;
// assign by initializer list
bar.push_back({.a = 1});
}
int main () {
broken_demo();
}
Compiler Error:
clang++ -std=c++11 -Wall -Wextra -Wfatal-errors -pedantic -I./ -c -o demo.o demo.cpp
demo.cpp:13:20: warning: designated initializers are a C99 feature [-Wc99-extensions]
bar.push_back({.a = 1});
^~~~~~
In file included from demo.cpp:1:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/mutex:38:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/tuple:39:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/array:39:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/stdexcept:39:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/string:41:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/allocator.h:46:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33:
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/ext/new_allocator.h:146:8: fatal error: call to implicitly-deleted copy constructor of 'foo'
_Up(std::forward<_Args>(__args)...)))
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/alloc_traits.h:483:24: note: in instantiation of exception specification for
'construct<foo, foo>' requested here
noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:115:21: note: in instantiation of exception specification for 'construct<foo, foo>'
requested here
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_vector.h:1201:9: note: in instantiation of function template specialization
'std::vector<foo, std::allocator<foo> >::emplace_back<foo>' requested here
{ emplace_back(std::move(__x)); }
^
demo.cpp:13:9: note: in instantiation of member function 'std::vector<foo, std::allocator<foo> >::push_back' requested here
bar.push_back({.a = 1});
^
demo.cpp:6:16: note: copy constructor of 'foo' is implicitly deleted because field 'b' has a deleted copy constructor
std::mutex b;
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/std_mutex.h:94:5: note: 'mutex' has been explicitly marked deleted here
mutex(const mutex&) = delete;
^
I'm fairly certain that this is saying the reason this won't work is that the structure is attempting to call the copy constructor for the mutex, which in fact does not have a copy constructor. I explicitly don't want to do be doing this.
My initial thought is that in order to make sure it doesn't even try to call the copy constructor for the mutex, I can create my own constructor for my class and basically explicitly leave out the copying for the mutex. This method would look like this - but it also doesn't work.
#include <mutex>
#include <vector>
struct foo {
foo (int A): a(A) {;}
int a;
std::mutex b;
};
void broken_demo () {
std::vector<foo> bar;
// assign by initializer list
bar.emplace_back(1);
}
int main () {
broken_demo();
}
Compiler Error:
clang++ -std=c++11 -Wall -Wextra -Wfatal-errors -pedantic -I./ -c -o demo.o demo.cpp
In file included from demo.cpp:2:
In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/vector:65:
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_construct.h:75:38: fatal error: call to implicitly-deleted copy constructor of 'foo'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:83:8: note: in instantiation of function template specialization
'std::_Construct<foo, foo>' requested here
std::_Construct(std::__addressof(*__cur), *__first);
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:134:2: note: in instantiation of function template specialization
'std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<foo *>, foo *>' requested here
__uninit_copy(__first, __last, __result);
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:289:19: note: in instantiation of function template specialization
'std::uninitialized_copy<std::move_iterator<foo *>, foo *>' requested here
{ return std::uninitialized_copy(__first, __last, __result); }
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:310:19: note: in instantiation of function template specialization
'std::__uninitialized_copy_a<std::move_iterator<foo *>, foo *, foo>' requested here
return std::__uninitialized_copy_a
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:473:10: note: in instantiation of function template specialization
'std::__uninitialized_move_if_noexcept_a<foo *, foo *, std::allocator<foo> >' requested here
= std::__uninitialized_move_if_noexcept_a
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:121:4: note: in instantiation of function template specialization 'std::vector<foo,
std::allocator<foo> >::_M_realloc_insert<int>' requested here
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
^
demo.cpp:15:9: note: in instantiation of function template specialization 'std::vector<foo, std::allocator<foo> >::emplace_back<int>' requested here
bar.emplace_back(1);
^
demo.cpp:8:16: note: copy constructor of 'foo' is implicitly deleted because field 'b' has a deleted copy constructor
std::mutex b;
^
/usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/std_mutex.h:94:5: note: 'mutex' has been explicitly marked deleted here
mutex(const mutex&) = delete;
^
1 error generated.
Any thoughts on a solution to this? I'm hoping to keep the code relatively simple, but I'm uncertain how to make the standard vector behave, or at least use it properly.
The problem is that in your code instances of foo are passed by value. So when you put something into the vector, a copy needs to be created. A simple way to avoid that would be to put pointers to foo into the vector. You can wrap the pointers into some reference-counting mechanism so that you don't have to keep track of freeing the objects.
Here is a short example using std::unique_ptr that will auto-delete all foo instances in the vector when the vector goes out of scope:
#include <mutex>
#include <vector>
#include <memory>
#include <iostream>
#include <functional>
struct foo {
foo(int A) : a(A) {}
int a;
std::mutex b;
};
void fixed_demo () {
std::vector<std::unique_ptr<foo>> bar;
std::unique_ptr<foo> p(new foo(1));
bar.push_back(std::move(p));
bar.emplace_back(new foo(2));
for (auto it = bar.begin(); it != bar.end(); ++it) {
(*it)->b.lock();
std::cout << (*it)->a << std::endl;
(*it)->b.unlock();
}
}
int main () {
fixed_demo();
return 0;
}
After looking at one of the solutions, I think actually this solution fits best what I was going for. I wouldn't have been able to figure this out without the helpful advice above.
#include <mutex>
#include <vector>
struct foo {
int a;
std::mutex b;
foo (int a) : a(a) {;}
foo (const foo &f) : a(f.a) {;}
};
void other_fixed_demo ()
{
std::vector<foo> bar;
bar.emplace_back(1);
}
int main () {
other_fixed_demo();
}
I couldn't say why, but apparently two things are happening here. First, we are calling the constructor with the 1 input, and then somewhere within emplace_back() we're calling the copy constructor. Both need to explicitly not include the mutex in each way of creating the struct, and the above solution avoids that.
How to add object of class to vector in another class.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class info{
private:
int id;
string name;
public:
info(int extId, string extName) {
this->id = extId;
this->name = extName;
}
};
class db {
private:
vector<info> infoVector;
public:
void pushData(info * data) {
this->infoVector.push_back(&data);
}
};
int main(){
info * testData = new info(123, "nice");
db database;
database.pushData(testData);
return 0;
}
I am creating a object of info class. The object contains one int and one string variables. Then I am creating db object and I am passing there a testData object.
I got error message while building project.
main.cpp: In member function ‘void db::pushData(info*)’:
main.cpp:23:44: error: no matching function for call to ‘std::vector<info>::push_back(info*&)’
this->infoVector.push_back(data);
^
In file included from /usr/include/c++/5/vector:64:0,
from main.cpp:2:
/usr/include/c++/5/bits/stl_vector.h:913:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = info; _Alloc = std::allocator<info>; std::vector<_Tp, _Alloc>::value_type = info]
push_back(const value_type& __x)
^
/usr/include/c++/5/bits/stl_vector.h:913:7: note: no known conversion for argument 1 from ‘info*’ to ‘const value_type& {aka const info&}’
What am I doing wrong?
It looks like you are trying to pass the address of an info * type to vector<info>::push_back, which only accepts types of const info & or info &&. Try using the dereference operator * instead of the address-of operator & when you call push_back:
this->infoVector.push_back(*data);
This isn't a great way to use pointers, however, and could lead to memory leakage or segfaults if data is removed from the vector or if it is deleted. It is better for the vector to own its members, so you might consider doing this instead:
class db {
private:
vector<info> infoVector;
public:
void pushData(info data) { // note: not a pointer
this->infoVector.push_back(data); // note: not address-of
}
};
int main(){
info testData(123, "nice"); // note: not a pointer
db database;
database.pushData(testData);
return 0;
}
Otherwise, if you really want infoVector to contain pointers, declare it as:
std::vector<info*> infoVector;
Then remove the address-to operator.
P.S., avoid using namespace std whenever possible!
You have vector<info> and you want to put info *, try to do:
int main(){
info testData(123, "nice");
db database;
database.pushData(testData);
return 0;
}
#include <vector>
#include <thread>
int main()
{
vector<int> a;
thread s(&vector<int>::push_back,&a,3);
}
I get compile error for these code:
main.cpp:52:39: error: no matching function for call to
‘std::thread::thread(<unresolved overloaded function type>, std::vector<int>*, int)’
thread s(&vector<int>::push_back,&a,3);
can I get any help?
The error is telling you that it doesn't know which overload of vector<int>::push_back to use,
void vector<int>::push_back(const int& val);
or
void vector<int>::push_back(int&& val);
since they both have the same name.
The solution is to static_cast to the required function type, or declare a variable of the correct type,
e.g.
thread s(static_cast<void(vector<int>::*)(const int&)>(&vector<int>::push_back),&a,3);
or
void (vector<int>::* func)(const int&) = &vector<int>::push_back;
thread s(func, &a, 3);
I know, it's horribly ugly.
You can try passing a lambda:
thread s([](vector<int>& a, int b) {
a.push_back(b);
}, std::ref(a), 3);
I have a Load-Method which builds my unique_ptr (will be more than one later on) and a method to add these unique_ptr to my unordered map. But the code does not compile and I guess it has something to do with scoping...
Here is the code:
#include <unordered_map>
#include <memory>
class MyClass
{
public:
std::string Name;
};
using Map = std::unordered_map<std::string,std::unique_ptr<MyClass>>;
class MyContainer
{
private:
Map myMap;
void AddItem(std::unique_ptr<MyClass> item)
{
myMap.emplace("test", item);
}
public:
void LoadItems()
{
//Read a file ... do something before etc..
std::unique_ptr<MyClass> someItem(new MyClass);
someItem->Name = "FooBar";
AddItem(someItem);
}
};
This is one of the g++ error messages:
error: use of deleted function 'std::unique_ptr<_Tp,
_Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = MyClass; _Dp = std::default_delete]'
What is the best way to get this working? I tried changing the signature of the AddItem-method like so:
void AddItem(std::unique_ptr<MyClass>& item) //takes a reference now...
This leads to a real cryptic error message:
In instantiation of 'constexpr std::pair<_T1, _T2>::pair(_U1&&, const
_T2&) [with _U1 = const char (&)[5]; = void; _T1 = const std::basic_string; _T2 = std::unique_ptr]': e:\devtools\winbuilds\include\c++\4.8.3\bits\hashtable_policy.h:177:55:
required from 'std::__detail::_ ...
I suggest trying this piece of code on the fly here, to see the error messages:
http://cpp.sh/
You cannot copy a unique_ptr, because then it will not be unique. You have to move it - AddItem(std::move(someItem)); and myMap.emplace("test", std::move(item));.
You are trying to copy unique_ptr which is not allowed (that constructor is deleted as gcc says in the error). Instead of that you can try with std::move:
#include <unordered_map>
#include <memory>
#include <utility>
class MyClass
{
public:
std::string Name;
};
using Map = std::unordered_map<std::string,std::unique_ptr<MyClass>>;
class MyContainer
{
private:
Map myMap;
void AddItem(std::unique_ptr<MyClass> item)
{
myMap.emplace("test", std::move(item));
}
public:
void LoadItems()
{
//Read a file ... do something before etc..
std::unique_ptr<MyClass> someItem(new MyClass);
someItem->Name = "FooBar";
AddItem(std::move(someItem));
}
};
Be aware, do not use the moved object afterwards.
You can consider to use shared_ptr instead.