In C ++ 98 und C ++ 03 funktioniert die Template-Argumentableitung nur mit Funktionen (und Methoden).
Ich glaube nicht, dass sich das Bild in den neueren Standards geändert hat.
Mein Template-Fu ist ziemlich schwach. Ich habe diesen Code:
%Vor% ... aber ich möchte etwas, das lesbarer ist als Cs fiese Funktion Pointer-Syntax von void(*func)(T*)
.
Jemand in meinem Team hat dies vorgeschlagen:
%Vor%(Ich diskutiere immer noch, ob das tatsächlich lesbarer ist, aber das ist ein separates Problem.)
Wie kann ich dem Compiler helfen herauszufinden, was T ist, ohne es explizit im Aufrufer angeben zu müssen?
Sie können T
aus dem Funktionstyp mithilfe einer Merkmalsklasse extrahieren.
Ihr Beispiel kann wie folgt geändert werden:
%Vor%Diese Technik wird in der Boost-Typ-Traits-Bibliothek verwendet: Ссылка
Dieser Blogeintrag geht ein bisschen genauer auf die Implementierung der Technik ein: Ссылка
Leider verbirgt dieser Ansatz die Informationen in der Signatur von Foo
über die Einschränkungen des übergebenen Arguments. Im obigen Beispiel muss das Argument eine Funktion vom Typ void(T*)
sein.
Diese alternative Syntax macht das gleiche wie das ursprüngliche Beispiel und ist etwas besser lesbar:
%Vor%Eine andere alternative Syntax, die besser lesbar ist, kann mit den Alias-Vorlagen von C ++ 11 wie folgt erreicht werden:
%Vor%Leider kompiliert die neueste MSVC das nicht und meldet einen internen Compilerfehler.
Sie können den Typ basierend auf einem verschachtelten Namen nicht ableiten: Es gibt keinen Grund, warum verschiedene Instanziierungen des äußeren Typs keinen identischen inneren Typ definieren. Sie könnten jedoch einen using
Alias verwenden:
Persönlich würde ich jedoch davon abraten, eines davon zu verwenden: In der Praxis erscheint es viel sinnvoller, ein Funktionsobjekt zu verwenden, das es später ermöglicht, ein Objekt mit geeigneten Funktionsaufrufoperatoren zu verwenden. Bei Callbacks ist es üblich, dass Sie Hilfsdaten eingeben müssen. Das heißt, Sie würden entweder eine unbeschränkte Vorlage verwenden oder eine, die einen Typ gelöscht hat, abhängig davon, was genau Sie tun möchten:
%Vor% Die unbeschränkte Version hat den Vorteil, dass sie den Funktionsaufruf potenziell inline machen kann, aber sie hat den Nachteil, dass jeder Funktionsobjekttyp eine neue Instanziierung erzeugt und dass die Argumenttypen wahrscheinlich variieren. Die Typ-gelöschte Version muss tatsächlich so etwas wie einen virtuellen Funktionsaufruf machen, aber es gibt nur eine Instanz der Funktionsvorlage (pro Argumenttyp T
, natürlich).
Der Typ der gelöschten Version wird zwar nicht von einem Funktionszeiger (oder irgendeinem anderen Argument, das kein std::function<void(X*)>
ist) abgeleitet, d. h., Sie möchten möglicherweise eine Weiterleitungsfunktion haben