2009-03-07 4 views
0

J'utilise des templates C++ pour passer dans les foncteurs Strategy pour changer le comportement de ma fonction. Ça fonctionne bien. Le foncteur que je passe est une classe sans état sans stockage et surcharge juste l'opérateur() de la manière classique des foncteurs.Classe Functor travaillant dans le constructeur

template <typename Operation> int foo(int a) 
{ 
int b=Operation()(a); 
/* use b here, etc */ 
} 

Je le fais souvent, et il fonctionne bien, et souvent je fais des modèles avec 6 ou 7 foncteurs templated passé en!

Cependant, je m'inquiète à la fois de l'élégance du code et de l'efficacité. Le foncteur est sans état, donc je suppose que le constructeur Operation() est libre et l'évaluation du foncteur est aussi efficace qu'une fonction inline, mais comme tous les programmeurs C++, j'ai toujours des doutes persistants.

Ma deuxième question est de savoir si je pourrais utiliser une autre approche des foncteurs .. celle qui ne remplace pas l'opérateur(), mais fait tout dans le constructeur comme effet secondaire! Quelque chose comme:

struct Operation { 
    Operation(int a, int &b) { b=a*a; } 
}; 
template <typename Operation> int foo(int a) 
{ 
    int b; 
    Operation(a,b); 
    /* use b here, etc */ 
} 

Je ne l'ai jamais vu quelqu'un utiliser un constructeur comme le « travail » d'un foncteur, mais il semble que cela devrait fonctionner. Y a-t-il un avantage? Un inconvénient? J'aime la suppression de l'étrange parenthèse doublée "Operator() (a)", mais c'est probablement juste esthétique.

Répondre

2

Un désavantage?

  • cteurs ne renvoyer aucune valeur utile - ne peut pas être utilisé dans les appels chaînés (par exemple foo (bar())
  • Ils peuvent jeter
  • point de vue de la conception -.. Ctors sont fonctions de création d'objets, pas vraiment destinés à être bêtes de somme.
+0

Qui ne peut pas lancer? –

+0

@Mykola Golubyev: Dtors - au moins, vous n'êtes pas censé jeter. – dirkgently

1
  1. Compilateurs inline en fait le constructeur vide de l'opération (au moins gcc dans des situations similaires ne, sauf si vous avez désactivé l'optimisation)
  2. L'inconvénient de tout faire dans le constructeur est que vous ne pouvez pas créer un foncteur avec certains état interne de cette façon - par exemple. foncteur pour compter le nombre d'éléments satisfaisant un prédicat. En outre, l'utilisation d'une méthode d'un objet réel en tant que foncteur vous permet de stocker l'instance pour une exécution ultérieure, ce que vous ne pouvez pas faire avec votre approche constructeur.
1

d'un pov performance du code démontré avec obtenir optimisé complètement avec les deux VC et le CCG. Cependant, une meilleure stratégie est souvent de prendre le foncteur comme paramètre, que comme vous obtenez beaucoup plus de flexibilité un nd caractéristiques de performance identiques.

0

Je vous recommande de définir un foncteur qui fonctionne avec les conteneurs STL, c'est-à-dire qu'ils doivent implémenter operator(). (Suivre l'API du langage que vous utilisez est toujours une bonne idée.)

Cela permet à vos algorithmes d'être très génériques (fonctions pass, functors, stl-bind, boost :: function, boost :: bind , boost :: lambda, ...) qui est ce que l'on veut habituellement.

De cette façon, vous n'avez pas besoin de spécifier le type de foncteur en tant que paramètre de modèle, simplement construire une instance et le transmettre dans:

my_algorithm(foo, bar, MyOperation()) 
0

Il ne semble pas tout moment dans la mise en œuvre du constructeur dans un autre classe.
Tout ce que vous faites est de casser l'encapsulation et de mettre en place votre classe pour abus.

Le constructeur est supposé initialiser l'objet dans un bon état tel que défini par la classe. Vous autorisez un autre objet à initialiser votre classe. Quelles garanties avez-vous que cette classe modèle sait comment initialiser votre classe correctement? Un utilisateur de votre classe peut fournir n'importe quel objet qui pourrait perturber l'état interne de votre objet de manière non prévue.

La classe doit être autonome et s'initialiser à un bon état. Ce que vous semblez faire est de jouer avec des modèles juste pour voir ce qu'ils peuvent faire.

Questions connexes