OVH Cloud OVH Cloud

Interfaces & templates

8 réponses
Avatar
JBB
Bonjour,
J'ai une méthode paramétrée du style:

template < class MACLASSE>
void f(const MACLASSE & objet, int i)
{

objet.g(i);
}

Pour que ça marche il suffit que MACLASSE ai une méthode du 'g' genre:
class Machin
{ public:
void g(int i);
};
mon problème est aussi que 'g' peut être aussi:
class Truc
{public:
string g(char x, int z =0) const;
};
ce qui ne plait guère.

Du coup je fais une interface:
class InterfaceMaclasse
{ public:
virtual void g(int i)= 0;
};
Et je m'impose de dériver de cette interface.
class Machin : public InterfaceMaclasse
{ public:
virtual void g(int i);
};
Dans ce cas Truc ne marche pas.
Mais du coup Machin n'est plus une classe simple.
Elle recupère un pointeur de table de methodse virtuelles, et donc prends 4 octet au passage.
De plus dans l'absolu il faudrait que l'interface declare un destructeur virtuel.
Bref ca va modifier mon executable alors que je voulais juste un peu plus de contrôle à al compilation.

8 réponses

Avatar
Fabien LE LEZ
On Tue, 28 Feb 2006 11:40:34 +0100, JBB :

mon problème est aussi que 'g' peut être aussi:
class Truc
{public:
string g(char x, int z =0) const;
};
ce qui ne plait guère.


Regarde si <http://www.google.com/search?&q=boost%20static_assert> ne
pourrait pas t'aider.

Je suis presque sûr d'avoir vu un truc dans ce goût-là quelque part,
mais je ne me souviens plus si c'est dans Boost ou dans un
Exceptional C++.

Avatar
Fabien LE LEZ

Je suis presque sûr d'avoir vu un truc dans ce goût-là quelque part,


Bon, je n'arrive pas à le retrouver.
Je crois me souvenir que l'idée est de vérifier que Truc::g est bien
de type "fonction membre qui prend exactement un argument".

Avatar
Falk Tannhäuser
JBB wrote:
template < class MACLASSE>
void f(const MACLASSE & objet, int i)
{
objet.g(i);
}

Pour que ça marche il suffit que MACLASSE ai une méthode du 'g' ge nre:
class Machin
{ public:
void g(int i);


Il faut que g() soit qualifiée 'const' pour pouvoir l'appeler depuis
f(), ou bien il faut enlever le 'const' du paramètre 'object' dans f().

};
mon problème est aussi que 'g' peut être aussi:
class Truc
{public:
string g(char x, int z =0) const;
};
ce qui ne plait guère.


Une solution possible consiste à ajouter dans f() un paramètre
supplémentaire avec argument par défaut :

template<class MACLASSE>
void f(const MACLASSE& objet, int i, void (MACLASSE::*)(int) const = &MACLASSE::g)
{
objet.g(i);
}

...
Machin m; f(m, 42); // ça compile
Truc t; f(t, 666); // erreur de type pour l'argument par défaut

Falk

Avatar
Yoxoman

Une solution possible consiste à ajouter dans f() un paramètre
supplémentaire avec argument par défaut :

template<class MACLASSE>
void f(const MACLASSE& objet, int i, void (MACLASSE::*)(int) const = &MACLASSE::g)
{
objet.g(i);
}



Excellent !

--
"Yo!"
Martin Heidegger

Avatar
Fabien LE LEZ
On Tue, 28 Feb 2006 14:10:58 +0100, Falk Tannhäuser
:

Une solution possible consiste à ajouter dans f() un paramètre
supplémentaire avec argument par défaut :

template<class MACLASSE>
void f(const MACLASSE& objet, int i, void (MACLASSE::*)(int) const = &MACLASSE::g)
{


L'idée est bonne, mais pourquoi en faire un paramètre ?
Ne serait-ce pas mieux d'en faire une variable bidon ?

void f(const MACLASSE& objet, int i)
{
void (MACLASSE::* dummy)(int) const = &MACLASSE::g;
objet.g(i);
}

Avatar
Yoxoman

L'idée est bonne, mais pourquoi en faire un paramètre ?
Ne serait-ce pas mieux d'en faire une variable bidon ?

void f(const MACLASSE& objet, int i)
{
void (MACLASSE::* dummy)(int) const = &MACLASSE::g;
objet.g(i);
}


Pourquoi une variable ?

void f(const MACLASSE& objet, int i)
{
static_cast<void (MACLASSE::*)(int) const>(&MACLASSE::g);
objet.g(i);
}

:)

--
"Yo!"
Martin Heidegger

Avatar
kanze
Fabien LE LEZ wrote:

Je suis presque sûr d'avoir vu un truc dans ce goût-là
quelque part,


Bon, je n'arrive pas à le retrouver. Je crois me souvenir que
l'idée est de vérifier que Truc::g est bien de type "fonction
membre qui prend exactement un argument".


Je ne m'y connais pas vraiment dans la méta-programmation, mais
de tête, ça ne me semble pas si difficile. On prend l'adresse du
membre, qu'on affecte à un pointeur à fonction membre du type
voulu. Quelque chose du genre :

void (MACLASS::*pmf)( int ) = &MACLASS::g ;

Qu'il faut mettre quelque part où on est sûr qu'il soit
instantié, évidemment.

Mais au fond, pourquoi est-ce qu'on veut le faire ? Je n'ai pas
encore vraiment vu l'intérêt ici.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Fabien LE LEZ
On 28 Feb 2006 09:08:16 -0800, "kanze" :

Mais au fond, pourquoi est-ce qu'on veut le faire ?


J'avoue que ce petit détail m'a aussi échappé.