[C/C++] va_list

Le côté programmation du développement d'un jeu vidéo.

va_list

Messagepar NewbiZ » 25 Mai 2008, 05:13

Bonjour,

J'aurais voulu savoir s'il existait une méthode pour faire l'inverse d'une fonction avec ellipse.

C'est à dire que j'ai une fonction qui prend en paramètre un nombre variable d'arguments, ces arguments sont récupérés sous forme d'une va_list, et j'aimerais construire un autre appel avec.
En fait, je voudrais un moyen de "faire passer" mes arguments à une autre fonction.

Voici le code de la fonction qui recoit les arguments :

Code: Tout sélectionner
template <class IType, class MType>
class Timer
{
public:
  Timer();
  ~Timer();

  void setAction   ( MType  method   );
  void setInstance ( IType* instance );
  void init        ( IType* instance, MType method );

  void operator()  ( float seconds );
  void operator()  ( float seconds, void* data );

private:
  IType* m_instance;
  MType  m_method;
};

template <class IType, class MType>
void Timer<IType, MType>::operator()( float seconds, ... )
{
  // Récupération de la va_list
  (m_instance->*m_method)( /* arguments à placer ici */ );
}


Le but étant de pouvoir manipuler la chose de la manière suivante:
Code: Tout sélectionner
Starship s;
Timer<Starship, void (Starship::*) (int, bool)> t;
t.init( &s, &Starship::explode );
// On attend 5 secondes avant de lancer s.explode( 10, true )
t( 5, 10, true );

Dans l'idéal j'aurais même voulu déplacer le temps avant execution dans l'init, mais je n'ai pas trouvé de moyen de faire une fonction avec ellipse sans au moins un paramètre fixe :/ (Je suis preneur de solution aussi là dessus).

En remerciant ceux qui répondront!
~ Passer pour un idiot aux yeux d'un imbécile est une volupté de fin gourmet ~
Avatar de l’utilisateur
NewbiZ
 
Messages: 1265
Inscription: 02 Juin 2005, 22:25
Localisation: Tallinn / Estonie

Messagepar Loulou » 25 Mai 2008, 09:32

Là tu essayes de faire un truc compliqué un peu trop simplement ;)

Déjà, une manip à base d'ellipse est sale et ne fonctionnera de toute façon pas.

Ensuite, en prenant le pointeur de fonction via un type simple, tu perds toute information sur les paramètres. Or pour arriver à tes fins il faudrait que tu remplaces ton ellipse par les paramètres pris par la fonction passée en paramètre. D'un autre côté si tu explicites le type de la fonction, il faudra faire de nombreuses spécialisations (une par nombre de paramètres).

La solution simple serait d'utiliser boost::function et boost::bind. Ca éviterait le couplage entre la classe Timer et le fait qu'il soit appliqué à une certaine fonction membre d'une certaine classe, chose qu'il n'a absolument pas à savoir.

Code: Tout sélectionner
class Timer
{
    // ...

private :

    boost::function<void ()> m_method;
};

Starship s;
Timer t;
t.init( boost::bind(&Starship::explode, s, 10, true) );
// On attend 5 secondes avant de lancer s.explode( 10, true )
t( 5 );
Loulou
Hello World, I'm new !
 
Messages: 702
Inscription: 10 Avr 2005, 12:00

Messagepar NewbiZ » 26 Mai 2008, 01:22

Le problème, c'est que je ne peux pas incorporer boost au projet :00000025:
Je suis donc passé par une solution un peu plus moche, un peu plus fastidieuse, mais qui au final s'avère assez transparente pour l'utilisateur : une dizaine de surcharges templatées.

J'arrive maintenant à la partie où je dois multithreader tout ca => On en reparle sur le forum SFML :)
~ Passer pour un idiot aux yeux d'un imbécile est une volupté de fin gourmet ~
Avatar de l’utilisateur
NewbiZ
 
Messages: 1265
Inscription: 02 Juin 2005, 22:25
Localisation: Tallinn / Estonie

Messagepar Thelvyn » 26 Mai 2008, 08:48

tu peux le refaire à partir du boukin d'Alexandrescu, foncteurs + bind c'est pas très long... t'as la mémoire courte dis donc ;)
CoDito, ergo sum...
Avatar de l’utilisateur
Thelvyn
 
Messages: 488
Inscription: 31 Mai 2005, 20:40


Retourner vers Programmation

Qui est en ligne

Utilisateurs parcourant ce forum: Bing [Bot] et 18 invités