Generic function pointer in C ++ 11

I am currently writing a method execution queue in C ++ x0. I have implemented and tested the basic mechanism of the queue, but I want to change it with the ability to have push() automatically delete all previous calls to a particular method:

 queue.push(this, &Obj::foo, 1); queue.push(this, &Obj::foo, 2); queue.push(this, &Obj::foo, 3); 

should be the same as just calling

 queue.push(this, &Obj::foo, 3); 

My code so far looks like this:

Queue.h:

 #pragma once #include <functional> #include <vector> using std::vector; using std::function; using std::bind; class Queue { private: struct functioncall { std::function<void()> call; }; vector<functioncall> queue; public: Queue(); ~Queue(); template<typename T, typename F, typename... Args> int push(T, F , Args... args); int pop(); bool empty(); size_t size(); }; template<typename T, typename F, typename... Args> int Queue::push(T instance, F func, Args... args) { functioncall newelem = { bind(func, instance, args...) }; queue.push_back(newelem); return queue.size(); } 

Queue.cpp:

 #include "Queue.h" Queue::Queue() : queue() { } Queue::~Queue() { delete &queue; } int Queue::pop() { if(!queue.empty()) { queue.front().call(); queue.erase(queue.begin()); return queue.size(); } return 0; } bool Queue::empty() { return queue.empty(); } size_t Queue::size() { return queue.size(); } 

I have already prepared the queue vector to take a structure in which I want to not only save the result of std::bind , but also a pointer to the called method so that I can find this pointer and delete the old entries.

The problem is that functions passed to push() can take an arbitrary number of arguments. Is there a generic type of pointer (it doesn't have to be executable, just be the same when I re-push the same function into the queue) that can do this?

+4
source share
2 answers

In 5.2.10p10, you can put a pointer to the member function T::*(A1, A2, ...) on another pointer to the type of the member function U::*(B1, ...) and vice versa without losing information; std::less can compare pointers to member functions, so by dropping void (Impl::*)() to the member-pointer-member void (Impl::*)() you can compare the pointer to member functions with the same signature.

However, it is not guaranteed that a pointer to member functions with different signatures will differ when matching with the same pointer to a member type, so you will need to encode the signature in a comparable type. typeid will work here:

 auto key = std::make_pair(&typeid(F), reinterpret_cast<void (Queue::*)()>(func)); 

This suggests that F indeed a pointer to a member function; if the user tries to pass any other called object, then it will break.

+4
source

std::function::target<>() can be used to check the type of wrapped function:

 template <class F> bool is_same_call(const functionalcall& prevCall, F newCall) { const F* pf = prevCall.call.target<F>(); return pf ? *pf == newCall : false; } 

Note that std::function::target() will return nullptr if the function enclosed in std::function is of a type other than F

+3
source

All Articles