i search on google how to store and to execute functions (template function or not) passing in queue but i didn't find an enough good answer...
this is my code
Window.h
struct QueueEventFunction {
std::vector<std::function<void()>> v; // stores the functions and arguments
// as zero argument lambdas
template <typename F,/*template <typename U, typename = std::allocator<U> >*/ typename ...Args>
void Enqueue(F (*f), Args... args)
{
v.push_back([=] { f(args...); }); // add function and arguments
// as zero argument lambdas
// that capture the function and arguments
}
void CallAll()
{
for (auto f : v)
f(); // calls all the functions
}
};
class Window : public sf::RenderWindow {
public:
Window(sf::VideoMode window, const std::string& title, sf::Uint32 style = 7U, sf::ContextSettings settings = sf::ContextSettings());
~Window();
template <typename F, /*template <typename ...U > */typename ...Args>
void addQueue(F (*f), Args...args);
void execQueue();
private:
QueueEventFunction queue;
}
template <typename F, /*template <typename ...U >*/ typename ...Args>
void Window::addQueue(F (*f), Args...args) {
queue.Enqueue(f, std::forward<Args>(args)...);
}
void Window::execQueue() {
queue.CallAll();
}
TestWindow.cpp
template<typename T>
void add(T a, T b) {
return a b;
}
class foo{
public:
template<typename T> T add( T a, T b){ return a b;}
};
int main() {
Window window(sf::VideoMode(600, 600), "Test Window",7U,sf::ContextSettings());
window.addQueue(add<int>,1,2); // doesn't work
foo bar;
window.addQueue(&foo::add<int>,1,2); // doesn"t work
window.addQueue(bar.add<int>(1,2)); // doesn"t work
return 0;
}
i got a external symbol error. and if i put a function member class it simply doesn't work. (compilation error)
have you got an idea to correctly make the function addQueue<> with args ?
CodePudding user response:
The big problem with your code is that you take the function pointer as a pointer
template <typename F, typename ...Args>
void Enqueue(F (*f), Args... args)
and
template <typename F, typename ...Args>
void addQueue(F (*f), Args...args);
What you really want is
template <typename F, typename ...Args>
void Enqueue(F f, Args... args)
and
template <typename F, typename ...Args>
void addQueue(F f, Args...args);
And then you can pass any callable thing. Then you can use it with results of bind, lambdas, class member functions, class static member functions, and normal functions.
Then you can use it like
template<typename T>
int add(T a, T b) {
std::cout << "add(" << a << "," << b << ") -> " << a b << "\n";
return a b;
}
class foo{
public:
template<typename T>
T add( T a, T b) {
std::cout << "foo::add(" << a << "," << b << ") -> " << a b << "\n";
return a b;
}
template<typename T>
static T static_add( T a, T b) {
std::cout << "foo::static_add(" << a << "," << b << ") -> " << a b << "\n";
return a b;
}
};
int main() {
Window window(sf::VideoMode(600, 600),"Test Window",7U,sf::ContextSettings());
foo bar;
auto bar_add = [&bar](auto a,auto b){ return bar.add<int>(a,b); };
auto bind_add = std::bind(&foo::add<int>, &bar, std::placeholders::_1, std::placeholders::_2);
window.addQueue(bind_add,5,2);
window.addQueue(bar_add,5,2);
window.addQueue(add<int>,5,2);
window.addQueue(foo::static_add<int>,5,2);
window.execQueue();
return 0;
}
Try it here https://www.onlinegdb.com/t9WczrL-c