Frage

Ich bin mit C ++ Vorlagen in der Strategie functors passiere meine Funktion des Verhalten zu ändern. Es funktioniert gut. Die Funktors gebe ich staatenlos ist Klasse ohne Lagerung und Überlastungen nur den Operator () in der klassischen Funktors Art und Weise.

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

ich tun dies oft, und es funktioniert gut, und oft Vorlagen mit Ich mache 6 oder 7 Templat functors übergeben!

Allerdings bin ich sehr besorgt sowohl über Code Eleganz und auch die Effizienz. Der Funktor ist staatenlos so dass ich die Operation () Konstruktor ist kostenlos und die Auswertung des Funktor ist genauso effizient wie eine Inline-Funktion, aber wie alle C ++ Programmierer übernehme Ich habe immer einen nagenden Zweifel.

Die zweite Frage ist, ob ich einen alternativen Funktor Ansatz verwenden könnte .. eine, die nicht den Operator () enthebt, sondern tut alles im Konstruktor als Nebeneffekt! So etwas wie:

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 */
 }

Ich habe noch nie jemand einen Konstruktor als „Arbeit“ einen Funktors verwenden gesehen, aber es scheint, wie es funktionieren soll. Gibt es irgendeinen Vorteil? Jeder Nachteil? Ich mag die Entfernung des seltsamen verdoppelt Klammer „Operators () (a)“, aber das ist wahrscheinlich nur ästhetisch.

War es hilfreich?

Lösung

  

Jeder Nachteil?

  • ctors keine nützlichen Wert zurück -. (Z foo (bar ()) nicht in gekettet Anrufe verwendet werden
  • Sie können werfen.
  • Design-Sicht - ctors sind Objekterstellungsfunktionen, nicht wirklich gemeint Arbeitspferde sein.

Andere Tipps

  1. Compiler inline tatsächlich den leeren Konstruktor der Operation (mindestens gcc in ähnlichen Situationen der Fall ist, es sei denn, Sie ausgeschaltet Optimierung)
  2. Der Nachteil alles im Konstruktor zu tun, ist, dass Sie nicht einen Funktor mit einigem internen Zustand auf diese Weise erstellen können - zB. Funktors für die Anzahl der Elemente genügt ein Prädikat zu zählen. Auch als Funktors ein Verfahren zur Herstellung eines realen Objekts ermöglicht es Ihnen, die Instanz zu speichern für eine spätere Ausführung, etwas, das Sie nicht mit Ihrem Konstruktor Ansatz tun.

Aus Performance-pov demonstriert der Code mit vollständig mit sowohl VC und GCC optimiert bekommen. Doch oft eine bessere Strategie ist es, den Funktors als Parameter zu nehmen, da man so viel mehr Flexibilität und identische Leistungsmerkmale erhalten.

Ich würde empfehlen, Funktor definiert, die mit den STL-Containern arbeiten, das heißt, sie sollten Operator () implementieren. (Im Anschluss an die API der Sprache Sie verwenden ist immer eine gute Idee.)

, mit denen Sie Ihren Algorithmen sehr generisch sein (in Funktionen übergeben, functors, stl-bind, boost :: Funktion boost :: bind boost :: lambda, ...) das ist, was man in der Regel will.

Auf diese Weise brauchen Sie nicht den Funktors Typen als Template-Parameter angeben, nur eine Instanz erstellen und übergibt es an:

my_algorithm(foo, bar, MyOperation())

Es scheint keinen Punkt in den Konstruktor in einer anderen Klasse implementiert.
Alles was Sie brechen Kapselung und der Einrichtung Ihrer Klasse für Missbrauch tun.

Der Konstruktor soll das Objekt in einen guten Zustand initialisieren, wie sie in der Klasse definiert. Ermöglichen Sie es ein weiteres Ziel der Klasse zu initialisieren. Welche Garantien haben Sie, dass diese Template-Klasse weiß, wie Ihre Klasse richtig zu initialisieren? Ein Benutzer Ihrer Klasse kann ein beliebiges Objekt schaffen, das in einer Weise, nicht vorgesehen.

Chaos mit dem internen Zustand des Objekts könnte

sollte die Klasse in sich geschlossen und initialisieren sich zu einem guten Zustand. Was Sie scheinen mit Vorlagen zu tun, spielen nur um zu sehen, was sie tun können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top