Hello and sorry for my probably bad english,
I'm working on a pacman-like game, in C++0x ( because I want variadic templates ) , and I'm trying to make a template class around the SDL ( Simple Directmedia Layer, a game library ) timers. for people who don't know SDL, there are the two SDL functions related to the SDL timers :
|
SDL_TimerID SDL_AddTimer(Uint32 interval, Uint32 (*callback)(Uint32, void*), void *param);
|
This function tells the SDL to run the function pointed by the argument "callback" after "interval" milliseconds. This function gets two arguments, first, the "interval", and second, the void pointer "param", which can point on everything.
It ( the function ) must return a number in milliseconds, and it is re-run after this time. If it returns 0, it is never re-run.
|
void SDL_RemoveTimer(SDL_TimerID id)
|
When you create a timer with SDL_AddTimer, it returns a SDL_TimerID ( a simple typedef of int, or something, IMHO ) which can be passed to this function to stop the timer previousely created by SDL_AddTimer. It does nothing if the timer's function already returned 0.
I'm trying to make a template which takes a functor and a parameter pack, and uses a SDL timer to run this functor with an unsigned int ( the interval ) and the parameter pack as arguments after a specified time. The functor must return an unsigned int, which is used like the return of the function of an SDL timer.
I tried with an attribute :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
timer.hpp
#include <SDL/SDL.h>
template <typename Functor, typename... Args>
class Timer
{
public:
Timer (unsigned int interval, Functor functor, Args... args):m_functor(functor), m_args(args)
{
m_timerID = SDL_AddTimer(interval, Call, this);
}
~Timer ()
{
SDL_RemoveTimer(m_timerID);
}
private:
static Uint32 Call(Uint32 interval, void* that)
{
return (*(Timer*)that).m_functor(interval, (*(Timer*)that).m_args);
}
Functor m_functor;
Args... m_args;
SDL_TimerID m_timerID;
};
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
test.cpp
#include <iostream>
#include <functional>
#include "timer.hpp"
unsigned int sayHello(unsigned int)
{
using namespace std;
cout << "hello world\n" << endl;
return 0;
}
int main()
{
SDL_Init(SDL_INIT_TIMER);
Timer<std::function<unsigned int(unsigned int)>> timer(15, sayHello);
SDL_Delay(25); //sleep for 25 milliseconds, to allow the timer to be executed.
}
|
g++ says :
In file included from test.cpp:4:0:
timer.hpp:21:6: error: expected unqualified-id before ‘...’ token
timer.hpp: In constructor ‘Timer<Functor, Args>::Timer(unsigned int, Functor, Args ...)’:
timer.hpp:7:83: error: class ‘Timer<Functor, Args>’ does not have any field named ‘m_args’
timer.hpp: In static member function ‘static Uint32 Timer<Functor, Args>::Call(Uint32, void*) [with Functor = std::function<unsigned int(unsigned int)>, Args = {}, Uint32 = unsigned int]’:
timer.hpp:9:3: instantiated from ‘Timer<Functor, Args>::Timer(unsigned int, Functor, Args ...) [with Functor = std::function<unsigned int(unsigned int)>, Args = {}]’
test.cpp:15:69: instantiated from here
timer.hpp:18:68: error: ‘class Timer<std::function<unsigned int(unsigned int)> >’ has no member named ‘m_args’
|
I saw the following code in the C++0x standard :
1 2 3 4 5
|
template<class... Mixins>
class X : public Mixins... {
public:
X(const Mixins&... mixins) : Mixins(mixins)... { }
};
|
X inherits from its parameter pack, let's try :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
timer.hpp
#include <SDL/SDL.h>
template <typename Functor, typename... Args>
class Timer: public Args...
{
public:
Timer (unsigned int interval, Functor functor, Args... args):m_functor(functor), Args(args)...
{
m_timerID = SDL_AddTimer(interval, Call, this);
}
~Timer ()
{
SDL_RemoveTimer(m_timerID);
}
private:
static Uint32 Call(Uint32 interval, void* that)
{
return (*(Timer*)that).m_functor(interval, (*(Args*)that));
}
Functor m_functor;
SDL_TimerID m_timerID;
};
|
then :
In file included from test.cpp:4:0:
timer.hpp: In static member function ‘static Uint32 Timer<Functor, Args>::Call(Uint32, void*)’:
timer.hpp:18:60: error: parameter packs not expanded with ‘...’:
timer.hpp:18:60: note: ‘Args’
|
When I add an ellipsis after the right "Args" :
In file included from test.cpp:4:0:
timer.hpp: In static member function ‘static Uint32 Timer<Functor, Args>::Call(Uint32, void*)’:
timer.hpp:18:53: error: expected primary-expression before ‘...’ token
timer.hpp:18:53: error: expected ‘)’ before ‘...’ token
timer.hpp:18:64: error: expected ‘)’ before ‘;’ token
|
There is my "g++ --version" :
g++ (Debian 4.6.1-1) 4.6.1
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
Is it possible with the current C++0x draft ? If yes, How ? If not, is it planned in a future draft ? please help me.