Trying to create an asyncronous Observer pattern is causing a compiler error C3867, which I am clueless how to resolve it. The sample code snippet is as follows
class Subject;
class Observer
{
public:
virtual void notify(Subject* s) = 0;
virtual ~Observer() {};
};
class Subject
{
std::map<std::string, Observer *> observers;
protected:
void notify_observers()
{
std::map<std::string, Observer *>::iterator iter;
for (iter = observers.begin(); iter != observers.end(); ++iter) {
void (Observer::*notify)(Subject *) = iter->second->notify;
std::async(std::launch::async, notify, this);
}
}
public:
virtual ~Subject() {};
void observer(std::string id, Observer* o)
{
observers[id] = o;
}
};
template<typename Iter, typename type>
class Sort : public Observer {
public:
virtual void notify(Subject* s)
{
TestSort<Iter> *a;
a = dynamic_cast<TestSort<Iter> *>(s);
std::vector<type> temp(a->beg(), a->end());
sort(temp->beg(), temp->end());
}
};
template<typename Iter, typename type>
class InsertionSort : public Sort<Iter, type>
{
void sort(Iter beg, Iter end) {
for (Iter i = beg; i != end; ++i)
std::rotate(std::upper_bound(beg, i, *i), i, i+1);
}
};
int main ()
{
std::vector<double> data(100);
std::generate(data.begin(), data.end(), [](){return rand() % 500;} );
auto ts = TestSort<std::vector<double>::iterator >(data.begin(), data.end());
auto is = new InsertionSort<std::vector<double>::iterator, double >();
//.................
ts.observer("InsertionSort", is);
//.........................
ts.Triggerd();
return 0;
}
Though I understand the error
error C3867: 'Observer::notify': function call missing argument list; use '&Observer::notify' to create a pointer to member
Yet in this context I cannot figure out, how to resolve it.
In this context, if notify would had been a simply addreesable member function, instead of
void (Observer::*notify)(Subject *) = iter->second->notify;
I could have simply write
void (Observer::*notify)(Subject *) = &Observer::notify;
But notify is a polymorphic function and I cannot address the right function during compile time.
Please suggest how should I process
You don't need to figure out the right function during compile time, just as you don't have to figure it out for regular virtual function call. Just use &Observer::notify. The right function is selected at the time of call, not at the time of taking its address.
Change:
void (Observer::*notify)(Subject *) = iter->second->notify;
std::async(std::launch::async, notify, this);
To:
void (Observer::*notify)(Subject *) = &Observer::notify;
std::async(std::launch::async, std::mem_fun(notify), iter->second, this);
When you call a method, you need both the pointer-to-instance and arguments. The standard syntax is rettype retval = instance->method(arg);, but std::mem_fun will return a functor you can use like rettype retval = std::mem_fun(&InstanceType::method)(instance, arg); -- it makes the implicit this pointer passed to a member function explicit.
From a pointer to a virtual method, plus an object pointer, std::mem_fun can figure out which instance of the virtual method you should call.
A similar thing can be done with a bind or a lambda. Here is a roughly equivalent call using lambda syntax:
Observer* observer = iter->second;
std::async(std::launch::async, [observer,this]() { observer->notify(this); } );
See the comment below: you don't have to use std::mem_fun, async will do it for you. You do have to pass the instance pointer of the member function as the next argument still.
Related
Is there a way to match the address of a given parameter in an EXPECT_CALL?
I have code like the following:
EXPECT_CALL(mock1, GetTheData()).WillOnce(Return(theData));
EXPECT_CALL(mock2, SetTheData(_)); // How to check the parameter is the same object as the one returned by GetTheData
// the following was tried but does not work
EXPECT_CALL(mock2, SetTheData(_)).WillOnce([&theData](auto param){ EXPECT_EQ(&theData, param) })
But because the SetTheData function takes its argument by value, the address is different. So I would need to find a way to get the object, before it was passed to the SetTheData function.
I tried some stuff with matches, but that did not seem to work either.
Is this possible at all? If so, how? And if not, why not?
EDIT:
As requested here is a more complete example to give more context.
struct TheData
{
// some stl containers
std::unordered_map<int, std::array<std::byte, 16>> mapToArrays;
std::unordered_map<int, long long> mapToInts;
}
class IDataFetcher
{
public:
virtual TheData GetTheData() = 0;
}
class IDataReceiver
{
public:
virtual void SetTheData(TheData theData) = 0;
}
class DataFetcherMock : public IDataFetcher
{
public:
MOCK_METHOD(TheData, GetTheData, (), (override));
}
class DataReceiverMock
{
public:
MOCK_METHOD(void, SetTheData, (TheData), (override));
}
class Sut
{
public:
Sut(std::unique_ptr<IDataFetcher> fetcher, std::unique_ptr<IDataReceiver> receiver)
void DoTheThing()
{
mReceiver->SetTheData(mFetcher->GetTheData());
}
private:
std::unique_ptr<IDataFetcher> mFetcher;
std::unique_ptr<IDataReceiver> mReceiver;
}
TEST(TestFoo, TestGroupFoo)
{
auto fetcherMock = std::make_unique<DataFetcherMock>();
auto receiverMock = std::make_unique<DataReceiverMock>();
EXPECT_CALL(*fetcherMock, GetTheData()).WillOnce(Return(theData));
EXPECT_CALL(*receiverMock, SetTheData(_)); // Here I want to check the objects are the same
Sut sut(std::move(fetcherMock), std::move(receiverMock));
sut.DoTheThing();
}
I have a class named Handler wich stores some lambdas. What I want to do is to have a std::vector of std::function that stores all my events, for exemple. I really can't figure out why lambdas doesn't work as I expected.
Here's the handler.h:
class Handler
{
public:
Handler();
~Handler();
void Register(const char* outcome, std::function<auto()> lambda);
void Trigger(const char* outcome);
private:
std::vector<int> identifier;
std::vector<char*> outcome;
std::vector<std::function<auto()>> func;
};
And handler.cpp:
Handler::Handler()
{
//ctor stuff here
}
Handler::~Handler()
{
this->func.clear();
this->outcome.clear();
this->identifier.clear();
//...
}
void Handler::Register(const char* outcome, std::function<auto()> lambda)
{
static int identifier = 0;
identifier++;
this->outcome.push_back((char*)outcome);
this->identifier.push_back(identifier);
this->func.push_back(lambda);
//Sort outcome
}
void Handler::Trigger(const char * outcome)
{
int i;
for (i = 0; i < this->identifier.size(); i++)
{
if (!strcmp(outcome, this->outcome.at(i)))
break;
}
this->func[i]();
}
However, if I specify lambdas in a Handler::Register it wont let me throwing no suitable user-defined conversion from "lambda []void ()->void" to "std::function<auto()> exists. In this example I use void return type but other types also error, I don't understant why can't the template from std::function deduce it out, if it is what's happening.
Handler* events = new Handler();
events->Register("Up", [=]() -> void { //Error here!
//do stuff
//return something?
});
Is there any other way to do this, like without overloading Handler::Register?
auto is not a type, so std::function<auto()> is not a type either. From how you are using it, std::function<void()> is probably what you want.
There are other problems with your code, as noted in the comments, so I would change Handler to this
class Handler
{
public:
Handler();
// default ~Handler is fine
void Register(std::string outcome, std::function<void()> lambda);
void Trigger(const std::string & outcome outcome) const;
void Trigger(std::size_t index) const;
private:
using Outcomes = std::map<std::string, std::function<void()>/*, custom string comparator ?*/>;
std::vector<Outcomes::iterator> identifier;
Outcomes outcomes;
};
void Handler::Register(std::string outcome, std::function<void()> func)
{
auto emplaced = outcomes.emplace(std::move(outcome), std::move(func));
identifier.push_back(emplaced.first);
}
void Handler::Trigger(const std::string & outcome) const
{
outcomes.at(outcome)();
}
void Handler::Trigger(std::size_t index) const
{
identifier[index]->second();
}
Every time that I create a object, I store the pointer of that object in a vector, which is a static member of the class of the object, in order to monitor its state, something like this:
class A {
private:
static std::vector<A *> as;
STATE state = NONE; //<- enum
void doSomething();
public:
A() {
as.push_back(this);
}
static void monitor() {
auto end = as.end();
for (auto obj = as.begin(); obj != end; obj++) {
switch ((*obj)->state) {
//process it
(*obj)->doSomething();
}
}
}
}
//// recurrent call in other part of the program or even in other thread
A::monitor();
The above code is obviously incomplete, lacks an appropriately destructor, to remove the pointer of the vector that is being deleted.
the problem now is that I have to do the same with a template class
template <typename T>
class A {
void doSomething(); //<--independent, no template
....
}
Is there any way to do the same?, applying the independent type method "doSomething()" for every object?
If the function "doSomething()" was dependent type, there would be a way to accomplish the same?
You can do the same:
template <typename T>
class A {
private:
static std::vector<A<T>*> as;
STATE state = NONE; //<- enum
void doSomething()
public:
A() { as.push_back(this); }
static void monitor() {
auto end = as.end();
for (auto obj = as.begin(); obj != end; obj++) {
switch ((*obj)->state) {
//process it
(*obj)->doSomething();
}
}
}
}
template <typename T>
std::vector<A<T>*> as;
You just have to call
A<MyType>::monitor();
I need to make a class method take a template function as a pointer to function parameter, and then call it.
But I am running into
ThreadPool.hh:55:2: error: no matching function for call to ‘ThreadPoolElem<int>::start(<unresolved overloaded function type>, ThreadPoolElem<int>*)’
Samples and explanation of my code are :
I have a main module ThreadPool, which have a vector of ThreadPoolElem. As you may have guessed ThreadPoolElem are an encapsulation of Threads and ThreadPool plays the thread pool manager role. From ThreadPool I need to iterate the threadPoolElem vector. For each element in the vector I need to call its 'start' member function which take 2 argumens (the first one being a pointer to function). In the 'start' member function of The ThreadPoolElem class it uses the first argument as the callback for the third pthread_create c library function.
my threadpool file goest like this :
template <typename T>
class ThreadPool
{
Mutex _mutex;
CondVar _condVar;
SafeQueue<T> _tasks;
std::vector<ThreadPoolElem<T> > _threadVector;
/* .... */
void run(void)
{
for (typename std::vector<ThreadPoolElem<T> >::iterator it = this>_threadVector.begin();
it != this->_threadVector.end();
++it)
{
it->start(run_tramp, &(*it));
}
}
My ThreadPoolElem file goes like this:
template <typename T>
class ThreadPoolElem : public ThreadT<T>
{
SafeQueue<T> *_tasks;
CondVar *_condVar;
Mutex *_mutex;
public:
ThreadPoolElem(void) {}
void init(SafeQueue<T> *queue, CondVar *condVar, Mutex *mutex){
this->_mutex = mutex;
this->_condVar = condVar;
this->_tasks = queue;
}
void run(void){
while (true)
{
this->_mutex.lock();
if (this->_tasks.empty())
{
this->_condVar->wait();
this->_mutex->unlock();
}
else
{
int value;
this->_tasks->tryPop(&value);
std::cout << "consuming value" << std::endl;
if (!this->_tasks->empty())
{
this->_mutex->unlock();
this->_condVar->signal();
}
else
this->_mutex->unlock();
}
}
}
};
This is c like function (trampoline function) i need to take as a ptr to function parameter
template <typename T>
void *run_tramp(void *data)
{
reinterpret_cast<ThreadPoolElem<T> *>(data)->run();
return NULL;
}
And the final relevant file is :
template <typename T>
class ThreadT
{
public:
typedef enum
{
NOT_YET_STARTED,
RUNNING,
DEAD,
}thread_status;
private:
thread_status status_;
pthread_t thread_;
public:
/* .... */
void start(void *(*ptr)(void *), void* data){
this->status_ = RUNNING;
if (pthread_create(&this->thread_, NULL, ptr, data) != 0)
throw (SystemError("pthread_create"));
}
/* ...... */
};
You aren't using a templated function instantiation when you pass the pointer to your 'trampoline function' to the ThreadT<T>::start() method, you'll need to specify for which T it should be instantiated:
it->start(run_tramp<T>, &(*it));
// ^^^
I did quite a bit of searching, but the combination of * () and class scope has greatly hindered me in understanding of the syntax, with each edit throwing a new error, any help guys?
What I'm trying to do:
Declare a std::vector of pointers to member functions found in MyClass.h
Assign the actual member functions to the std::vector in MyClass.cpp's constructor
The member functions are not static
Thanks!
I'm curious where you're going to use them from. You see in order to call a C++ class member function you need to have an instance pointer with which to call it (each member function needs a this in order to access the class state). So normally you'd wrap the member function pointer together with the instance pointer with std::bind and then maybe store the result in std::function. To put them in vector they're all going to need the same signature.
Is this the kind of thing you were looking for:
class P
{
typedef std::function<void (void)> func_t;
std::vector<func_t> functions;
public:
P()
{
functions.push_back(std::bind(&P::foo1, this));
functions.push_back(std::bind(&P::foo2, this));
functions.push_back(std::bind(&P::foo3, this));
}
void foo1(void)
{
std::cout << "foo1\n";
}
void foo2(void)
{
std::cout << "foo2\n";
}
void foo3(void)
{
std::cout << "foo3\n";
}
void call()
{
for(auto it = functions.begin(); it != functions.end(); ++it)
{
(*it)();
}
}
};
int main()
{
P p;
p.call();
}
After further clarification from the OP I'll propose this:
class P
{
typedef std::function<void (void)> func_t;
std::map<const char*, func_t> functions;
public:
P()
{
functions["foo1"] = std::bind(&P::foo1, this);
functions["foo2"] = std::bind(&P::foo2, this);
functions["foo3"] = std::bind(&P::foo3, this);
}
void foo1(void)
{
std::cout << "foo1\n";
}
void foo2(void)
{
std::cout << "foo2\n";
}
void foo3(void)
{
std::cout << "foo3\n";
}
void call_by_name(const char* func_name)
{
functions[func_name]();
}
};
int main()
{
P p;
p.call_by_name("foo1");
p.call_by_name("foo2");
p.call_by_name("foo3");
}
You can use member function pointers like this (the C++11 is unrelated to that part):
struct S {
int foo(){std::cout<<"foo"; return 0;}
int bar(){std::cout<<"bar"; return 0;}
};
int main() {
std::vector<int(S::*)()> funcs{&S::foo, &S::bar};
S s;
for (auto func : funcs) {
(s.*func)();
}
}
However, if you use C++11, std::function can make it a bit cleaner:
std::vector<std::function<int(S &)>> funcs{&S::foo, &S::bar};
S s;
for (auto func : funcs) {
func(s);
}
If you use C++03, Boost has boost::function, which is similar.