This question already has answers here:
Start thread with member function
(5 answers)
Closed 9 years ago.
I'm just starting to use C++ 11 threads and I've been struggling on a (probably silly) error.
This is my example program:
#include <iostream>
#include <thread>
#include <future>
using namespace std;
class A {
public:
A() {
cout << "A constructor\n";
}
void foo() {
cout << "I'm foo() and I greet you.\n";
}
static void foo2() {
cout << "I'm foo2() and I am static!\n";
}
void operator()() {
cout << "I'm the operator(). Hi there!\n";
}
};
void hello1() {
cout << "Hello from outside class A\n";
}
int main() {
A obj;
thread t1(hello1); // it works
thread t2(A::foo2); // it works
thread t3(obj.foo); // error
thread t4(obj); // it works
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
Is it possible to start a thread from a pure member function? If it is not, how can I wrap my foo function from object obj to be able to create such thread?
Thanks in advance!
This is the compiling error:
thread_test.cpp: In function ‘int main()’:
thread_test.cpp:32:22: error: no matching function for call to ‘std::thread::thread()’
thread_test.cpp:32:22: note: candidates are:
/usr/include/c++/4.6/thread:133:7: note: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (A::*)(), _Args = {}]
/usr/include/c++/4.6/thread:133:7: note: no known conversion for argument 1 from ‘’ to ‘void (A::*&&)()’
/usr/include/c++/4.6/thread:128:5: note: std::thread::thread(std::thread&&)
/usr/include/c++/4.6/thread:128:5: note: no known conversion for argument 1 from ‘’ to ‘std::thread&&’
/usr/include/c++/4.6/thread:124:5: note: std::thread::thread()
/usr/include/c++/4.6/thread:124:5: note: candidate expects 0 arguments, 1 provided
You need a callable object taking no parameters, so
thread t3(&A::foo, &obj);
should do the trick. This has the effect of creating a callable entity which calls A::foo on obj.
The reason is that a non-static member function of A takes an implicit first parameter of type (possibly cv qualified) A*. When you call obj.foo() you are effectively calling A::foo(&obj). Once you know that, the above incantation makes perfect sense.
Related
This question already has an answer here:
c++ member function hides global function
(1 answer)
Closed 5 months ago.
#include <iostream>
#include <unistd.h>
using namespace std;
class A{
public:
bool close(){ return true; }
};
class B: public A{
public:
void fun(){
(void) close(1);
}
};
int main() {
B b;
b.fun();
return 0;
}
In class B I want to call the function close(1) which is in library unistd.h. FYI: close(int fileDes) used to close the file descriptors in process.
So how to overcome the issue. I got the below error:
source.cpp: In member function 'void B::fun()':
source.cpp:11:27: error: no matching function for call to 'B::close(int)'
11 | (void) close(1);
| ^
source.cpp:6:14: note: candidate: 'bool A::close()'
6 | bool close(){ return true; }
| ^~~~~
source.cpp:6:14: note: candidate expects 0 arguments, 1 provided
So how to overcome the issue, so that It will call the function in unistd.h file.
In the scope of the member function fun the name close as an unqualified name is searched in the scope of the class
void fun(){
(void) close(1);
}
And indeed there is another member function close in the base class with such a name.
So the compiler selects this function.
If you want to use a function from a namespace then use a qualified name as for example
void fun(){
(void) ::close(1);
}
This question already has answers here:
C++ Thread taking reference argument failed compile
(2 answers)
Closed 5 years ago.
I'm trying to do something like this:
void commands_conn_handler(int socket, RPiServer& server) {
// Not important code about handling connection
}
class RPiServer {
public:
void Accept(void Accept(void (*acceped_conn_handler)(int, RPiServer&)) {
// (...)
int remote_socket = 0; // Doesn't matter - example.
std::thread conn_handler_thread(acceped_conn_handler, remote_socket, *this);
conn_handler_thread.join();
}
};
int main() {
RPiServer commands_server();
commands_server.Accept(commands_conn_handler);
}
And when I try to build this, there are some errors:
In file included from /usr/include/c++/6/thread:39:0,
from src/rpi_server/rpiserver.cpp:11:
/usr/include/c++/6/functional: In instantiation of ‘struct std::_Bind_simple’:
/usr/include/c++/6/thread:138:26: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (*&)(int, RPiServer&); _Args = {int&, RPiServer&}]’
src/rpi_server/rpiserver.cpp:89:79: required from here
/usr/include/c++/6/functional:1365:61: error: no type named ‘type’ in ‘class std::result_of’
typedef typename result_of<_Callable(_Args...)>::type result_type;
^~~~~~~~~~~
/usr/include/c++/6/functional:1386:9: error: no type named ‘type’ in ‘class std::result_of’
_M_invoke(_Index_tuple<_Indices...>)
^~~~~~~~~
Makefile:29: recipe for target 'build/rpi_server/rpiserver.o' failed
When I change thread function in following way (remove reference to object):
void commands_conn_handler(int socket) {
// Not important code about handling connection
}
class RPiServer {
public:
void Accept(void (*acceped_conn_handler)(int)) {
// (...)
int remote_socket = 0; // Doesn't matter - example.
std::thread conn_handler_thread(acceped_conn_handler, remote_socket);
conn_handler_thread.join();
}
};
int main() {
RPiServer commands_server();
commands_server.Accept(commands_conn_handler);
}
Everything builds perfectly fine. What I'm doing wrong when I'm passing reference as parameter to thread function?
So here you have a working example:
#include <thread>
#include <functional>
class RPiServer;
void commands_conn_handler(int socket, RPiServer &server) {
// Not important code about handling connection
}
class RPiServer {
public:
void Accept(void (*acceped_conn_handler)(int, RPiServer&)) {
// (...)
int remote_socket = 0; // Doesn't matter - example.
std::thread conn_handler_thread(acceped_conn_handler, remote_socket, std::ref(*this));
conn_handler_thread.join();
}
};
int main() {
RPiServer commands_server;
commands_server.Accept(commands_conn_handler);
}
The error you was getting was because you were not providing correct type for the constructor of conn_handler_thread. To explicitly get a reference to an object (which you need to do here), use a std::ref() function.
P.S.: Also you copy pasted your code example wrong, duplicating the void Accept part. You also had a most vexing parse error in main().
In my actual code, I included a library, and as soon as I did that, it started crashing. I managed to sort of extract some of that code into this minimal example, that demonstrates the same kind of error:
// g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
#include <iostream>
#include <vector>
#include <stdio.h>
class Cat
{
public:
int Age;
Cat() : Age(0) {}
};
std::vector<Cat> myPCats;
typedef std::vector<Cat> TDVectCats;
TDVectCats myTDCats;
void loopSomeCats() {
printf("this function just to cause searching for matching calls\n");
}
void loopSomeCats(TDVectCats& incats) {
std::vector<Cat>::iterator iter;
for(iter = incats.begin(); iter != incats.end(); iter++) {
printf("hm\n");
}
}
const std::vector<Cat> & getSomeCats() {
return myPCats;
}
void doSomething() {
loopSomeCats(getSomeCats());
}
int main() {
myTDCats.push_back(Cat());
myTDCats.push_back(Cat());
myPCats.push_back(Cat());
doSomething();
std::cout << "Hello World! " << std::endl;
return 0;
}
The result is:
$ g++ -std=c++11 -g -o test-classcall.exe test-classcall.cpp
test-classcall.cpp: In function ‘void doSomething()’:
test-classcall.cpp:36:29: error: no matching function for call to ‘loopSomeCats(const std::vector<Cat>&)’
loopSomeCats(getSomeCats());
^
test-classcall.cpp:36:29: note: candidates are:
test-classcall.cpp:20:6: note: void loopSomeCats()
void loopSomeCats() {
^
test-classcall.cpp:20:6: note: candidate expects 0 arguments, 1 provided
test-classcall.cpp:24:6: note: void loopSomeCats(TDVectCats&)
void loopSomeCats(TDVectCats& incats) {
^
test-classcall.cpp:24:6: note: no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’
What especially confuses me, is the last "no known conversion for argument 1 from ‘const std::vector<Cat>’ to ‘TDVectCats& {aka std::vector<Cat>&}’", as if it cannot convert a vector of something, into the vector of the same something, just because of typedef? Or it maybe has to do with the const - but I simply cannot see what I need to change, in order to have a call like loopSomeCats(getSomeCats()); succeed...
You can't pass a reference to a const object to a non-const reference.
loopSomeCats takes a std::vector<Cat>& as argument, and you want to pass a const std::vector<Cat>& to it, but that's not possible.
The const would mean that you don't want anyone to modify the return value, but if you pass it to a function which just takes a non-const reference, then theoretically the function can modify the reference, and you don't want that.
You should drop the const if you want the return value to be modified.
Why are the function calls to waitForEvent in main below ambiguous?
#include <iostream>
struct Event1 { char c1[1]; };
struct Event2 { char c2[2]; };
template<class Event> struct EventSource
{
void waitForEvent(Event e) { std::cout << sizeof(e) << "\n"; };
};
typedef EventSource<Event1> Event1Source;
typedef EventSource<Event2> Event2Source;
struct Event12Source : public Event1Source, public Event2Source {};
int main()
{
Event12Source source;
source.waitForEvent(Event1());
source.waitForEvent(Event2());
return 0;
}
Compiling it I get the following errors:
user#AHERLADUSERVM2:~/test/TemplateMultipleMethodInheritance$ g++ test.cpp test.cpp: In function ‘int main()’: test.cpp:19:12: error: request for member ‘waitForEvent’ is ambiguous
source.waitForEvent(Event1());
^ test.cpp:7:10: note: candidates are: void EventSource<Event>::waitForEvent(Event) [with Event = Event2]
void waitForEvent(Event e) { std::cout << sizeof(e) << "\n"; };
^ test.cpp:7:10: note: void EventSource<Event>::waitForEvent(Event) [with Event = Event1] test.cpp:20:12: error: request for member ‘waitForEvent’ is ambiguous
source.waitForEvent(Event2());
^ test.cpp:7:10: note: candidates are: void EventSource<Event>::waitForEvent(Event) [with Event = Event2]
void waitForEvent(Event e) { std::cout << sizeof(e) << "\n"; };
^ test.cpp:7:10: note: void EventSource<Event>::waitForEvent(Event) [with Event = Event1]
(Why) is this not a simple case of function overloading resolution?
Thanks,
Damian
This may not be what you want, but it will solve the ambiguity
source.EventSource<Event1>::waitForEvent(Event1());
source.EventSource<Event2>::waitForEvent(Event2());
Also, if you are ever tempted to add a base class to Event1 and Event2, be aware of this
Because overloading does not work with inheritance. The derived class inherited the same function from two base classes which ambiguous.
This question already has answers here:
Start thread with member function
(5 answers)
Closed 9 years ago.
I'm just starting to use C++ 11 threads and I've been struggling on a (probably silly) error.
This is my example program:
#include <iostream>
#include <thread>
#include <future>
using namespace std;
class A {
public:
A() {
cout << "A constructor\n";
}
void foo() {
cout << "I'm foo() and I greet you.\n";
}
static void foo2() {
cout << "I'm foo2() and I am static!\n";
}
void operator()() {
cout << "I'm the operator(). Hi there!\n";
}
};
void hello1() {
cout << "Hello from outside class A\n";
}
int main() {
A obj;
thread t1(hello1); // it works
thread t2(A::foo2); // it works
thread t3(obj.foo); // error
thread t4(obj); // it works
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
Is it possible to start a thread from a pure member function? If it is not, how can I wrap my foo function from object obj to be able to create such thread?
Thanks in advance!
This is the compiling error:
thread_test.cpp: In function ‘int main()’:
thread_test.cpp:32:22: error: no matching function for call to ‘std::thread::thread()’
thread_test.cpp:32:22: note: candidates are:
/usr/include/c++/4.6/thread:133:7: note: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (A::*)(), _Args = {}]
/usr/include/c++/4.6/thread:133:7: note: no known conversion for argument 1 from ‘’ to ‘void (A::*&&)()’
/usr/include/c++/4.6/thread:128:5: note: std::thread::thread(std::thread&&)
/usr/include/c++/4.6/thread:128:5: note: no known conversion for argument 1 from ‘’ to ‘std::thread&&’
/usr/include/c++/4.6/thread:124:5: note: std::thread::thread()
/usr/include/c++/4.6/thread:124:5: note: candidate expects 0 arguments, 1 provided
You need a callable object taking no parameters, so
thread t3(&A::foo, &obj);
should do the trick. This has the effect of creating a callable entity which calls A::foo on obj.
The reason is that a non-static member function of A takes an implicit first parameter of type (possibly cv qualified) A*. When you call obj.foo() you are effectively calling A::foo(&obj). Once you know that, the above incantation makes perfect sense.