Why doesn't making threads like this work inside of an abstract base class? I'm trying to abstract away all of the multithreading details for users who derive from this base class. I don't understand why it says "no type named 'type'" when I clearly write that callbackSquare returns type int.
#include <iostream>
#include <future>
#include <vector>
class ABC{
public:
std::vector<std::future<int> > m_results;
ABC(){};
~ABC(){};
virtual int callbackSquare(int& a) = 0;
void doStuffWithCallBack();
};
void ABC::doStuffWithCallBack(){
for(int i = 0; i < 10; ++i)
m_results.push_back(std::async(&ABC::callbackSquare, this, i));
for(int j = 0; j < 10; ++j)
std::cout << m_results[j].get() << "\n";
}
class Derived : public ABC {
Derived() : ABC() {};
~Derived(){};
int callbackSquare(int& a) {return a * a;};
};
int main(int argc, char **argv)
{
std::cout << "testing\n";
return 0;
}
The strange errors I'm getting are:
/usr/include/c++/5/future:1709:67: required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = int (ABC::*)(int&); _Args = {ABC*, int&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = int]'
/usr/include/c++/5/future:1725:19: required from 'std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = int (ABC::*)(int&); _Args = {ABC*, int&}; typename std::result_of<_Functor(_ArgTypes ...)>::type = int]'
/home/taylor/Documents/ssmworkspace/callbacktest/main.cpp:16:69: required from here
/usr/include/c++/5/functional:1505:61: error: no type named 'type' in 'class std::result_of<std::_Mem_fn<int (ABC::*)(int&)>(ABC*, int)>'
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
/usr/include/c++/5/functional:1526:9: error: no type named 'type' in 'class std::result_of<std::_Mem_fn<int (ABC::*)(int&)>(ABC*, int)>'
_M_invoke(_Index_tuple<_Indices...>)
Your problem can be reproduced with any function that accepts a reference:
#include <future>
int f(int& a)
{
return a * a;
}
int main()
{
int i = 42;
auto r = std::async(f, i);
}
Accepting a reference in your code is risky since the variable will be modified by the loop iteration, creating a data race because the called function also accesses the variable.
Change the function to accept the input parameter by value, or call std::async by passing std::ref(i) or std::cref(i) (in case the function accepts a const reference) if you acknowledge the risk.
Related
//The header file
#include<iostream>
using namespace std;
int square(int);
//The actual code in square.cpp
int square(int x=10) {
return x * x;
}
//The function call in mainapp.cpp
int main(){
cout<< "Square is "<< square()<<"\n";
return 0;
}
I don't understand why CLion IDE underlines "pthread_create" and "pthread_join" in red and says "No matching function for call to...". I used a similar code without using the pointer to an object passed to the thread as an argument and it worked.
#include <iostream>
#include <pthread.h>
#define NUM_THREADS 4
using namespace std;
class Animal {
private:
float x, y;
public:
Animal(float x, float y) {
this->x = x;
this->y = y;
}
void print() {
cout<< x << "," << y << endl;
}
};
void *function(Animal *p) {
Animal animal = *p;
animal.print();
}
int main() {
pthread_t thread[NUM_THREADS];
Animal dog[] = {Animal(2, 3), Animal(-1, 2), Animal(5, 2), Animal(5, 10)};
for(int i = 0; i<NUM_THREADS; i++) {
pthread_create(&thread[i], NULL, function, &dog[i]);
}
for(int i = 0; i<NUM_THREADS; i++) {
pthread_join(thread[i]);
}
return 0;
}
I changed the argument of the childThread function from Animal to void *
void *childThread(void *p) {
Animal *animal = (Animal *)p;
animal->print();
}
And added a second argument NULL to pthread_join
pthread_join(thread, NULL)
and now it works
I am creating a class that has two members string and int
I want to use the constructor to initialize both of these two members to use them.
#pragma once
#include <string>
#include <iostream>
using namespace std;
class donation_1
{
public:
//string name;
const char* name;
int donation_amount;
const static size_t string_size = sizeof(string);
const static size_t int_size = sizeof(int);
donation_1(char* name_1 = "Noname", int amount = 0) : name(name_1), donation_amount(amount) {};
};
int main()
{
fstream file;
file.open("donation_total1.txt", ios_base::app);
if (file.is_open())
{
donation_1("xxxx", 20).writedata(file);
donation_1("yyyy", 30).writedata(file);
donation_1("zzzz", 40).writedata(file);
donation_1("MMMM", 50).writedata(file);
donation_1("BBBB", 60).writedata(file);
file.close();
}
else
{
cout << "file couldn't be opened" << endl;
}
return 0;
}
I want to use the constructor to initialize the class variables which I will be using to update a file, however, what I am getting is this error. this error is regarding initializing the string class member.
Severity Code Description Project File Line Suppression State
Error (active) E0310 default argument of type "const char *" is incompatible with parameter of type "char *" Stream_File_Lab D:\INVSPRIVATE\C++\Projects\Stream_File_Lab\donation_1.h 17
The error message is makes it pretty clear. The variable 'name' is declared as const char* but the value being assigned to it is only char* i.e. the const-ness is missing, hence the type incompatibility error throws up.
Please, google for pointer to a const value and how to use them.
Maybe check this tutorial
I have some homework, and I have troubles understanding, (probably) how passing parameters to std::thread constructor works.
Assume following code (I deleted unneeded parts)
template<typename T, typename Task>
class Scheduler
{
private:
typedef std::unordered_map<std::size_t, T> Results;
class Solver
{
public:
Solver(Task&& task) : m_thread(&Solver::thread_function, std::move(task))
{
m_thread.detach();
}
Solver(Solver&& solver) = default; // required for vector::emplace_back
~Solver() = default;
private:
void thread_function(Task&& task)
{
task();
}
std::thread m_thread;
};
public:
Scheduler() = default;
~Scheduler() = default;
void add_task(Task&& task)
{
m_solvers.emplace_back(std::move(task));
}
private:
std::vector<Solver> m_solvers;
};
template<typename T>
struct Ftor
{
explicit Ftor(const T& t) : data(t) { }
T operator()() { std::cout << "Computed" << std::endl; return data; }
T data;
};
int main()
{
Scheduler<int, Ftor<int>> scheduler_ftor;
Scheduler<int, std::function<int(void)>> scheduler_lambda;
Ftor<int> s(5);
scheduler_ftor.add_task(std::move(s));
scheduler_lambda.add_task([](){ std::cout << "Computed" << std::endl; return 1; });
}
Why it doesn't compile?
MVS2015 is complaining about
functional(1195): error C2064: term does not evaluate to a function taking 1 arguments
functional(1195): note: class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
note: while compiling class template member function 'Scheduler<int,Ftor<int> >::Solver::Solver(Task &&)'
While G++ 4.9.2
functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’:
required from ‘void Scheduler<T, Task>::add_task(Task&&) [with T = int; Task = Ftor<int>]’
functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
I suppose there are some problems with std::moving to std::thread.
If you use member function as first thread argument, second argument supposed to be this pointer, pointing to the object to which member function could be called to
UPDATE
Good discussion here
Start thread with member function
I don't follow your code, but addressing the question, a extrapolated answer will be( most of the code is psuedocode)
lets assume that there is a function int test(int name).
thread t0;
t0 = thread(test,32);
thread t1(test,43);
Passing a argument to function.
int temp = 0;
int testfunc(int& q)
{
cout<<q;
}
thread t1;
t1 = thread(testfunc,ref(temp));
In short, you just pass the name of the function that must be run in the thread as the first argument, and the functions parameters follow it in same order as they are in the function definition, for passing by reference you can use the ref() wrapper.See the below example.
#include <iostream>
#include <thread>
#include <string>
using namespace std;
void test(int a,int &a,string test)
{
\\do something
}
int main()
{
int test1 = 0;
string tt = "hello";
thread t1;
t1 = thread(23,&test1,tt);
t1.detach();
return 0;
}
if you are wondering about the use of join() and detach(), refer to this thread: When should I use std::thread::detach?, refer to my answer post in that thread.
I'm trying to write some code that can execute a class member function in a separate thread, but with some added code for checking odds and ends before and after the thread has executed.
For this I'm using the std::bind and std::thread functionality of c++11 in VS2012.
All this works well if I fix the arguments the class member function can have to e.g. void*, but if I try to template that, I get an error.
Overview of Code
I have a simple class containing two functions, which will be executed in a thread. They differ in arguments and name.
The class I'm creating has a templated constructor and a function, which executes the functions of the previous class, but with the ability to perform it's own checks/notifications if the thread does/does not finish.
Finally the main function is simply to test the code.
The Code
Include Part:
#include <iostream>
#include <memory>
#include <thread>
#include <functional>
using namespace std;
Class to be executed:
class k1
{
public:
k1( int nVal = 0 ) : _val(nVal){};
~k1(){};
void doFunc( void * pParam ){
cout << "Val in class = " << _val << ", param = " << pParam << "\n";
}
void doFunc2( float pParam ){
cout << "Val in class = " << _val << ", param = " << pParam << "\n";
}
int _val;
};
typedef shared_ptr<k1> PK;
Thread Handle Class
class H
{
public:
void controlFunction( std::function<void(void)> callRef ){
cout << "Before calling\n";
callRef();
cout << "After calling\n";
}
template<class T, typename ParamType> // Constructor for any type of class function - void * parameter as only input
H( void(T::* pFunction)(ParamType *), T * pClass, ParamType pParam ){
std::function<void(void)> _call = std::bind( pFunction, pClass, pParam );
_thread = shared_ptr<std::thread>( new thread( &H::controlFunction, this, _call ));
}
~H( void ){
_thread->join();
}
shared_ptr<thread> _thread;
};
typedef shared_ptr<H> PH;
Main Function:
int main(int argc, char* argv[])
{
PK k = make_shared<k1>( 12 );
int i1 = 2;
float f1 = 1.0f;
PH p = PH( new H(&k1::doFunc, k.get(), &i1 ));
PH p2 = PH( new H(&k1::doFunc2, k.get(), f1 ));
return 0;
}
The error that comes out is:
error C2660: 'H::H' : function does not take 3 arguments
Thanks in advance!
/Henrik
I'm guessing that you get the error on the second line where you create a H object taking k1::doFunc2 as argument. The probable reason for the error is because k1::doFunc2 doesn't take a pointer for argument, while the member function pointer argument in the H constructor expects it to.
There is also some problems with the first line, when you declare the p variable. This is because then the ParamType template type can be deduced to be either int or int*. The reason for this is because the member function pointer have ParamType *, while the third argument to the constructor uses non-pointer ParamType but you pass a pointer here (&i1).