2013-02-19 5 views
7
#include <functional> 

void f1(int) 
{} 

void f2(int, ...) 
{} 

int main() 
{ 
    std::function<void(int)>  g1 = f1; // OK. 
    std::function<void(int, ...)> g2 = f2; // Error! Not standard C++! 
} 

Warum Klasse nicht C++ 11 nicht eine spezielle Vorlage, wie folgt:Warum unterstützt C++ 11 'std :: function <void (int, ...)>' nicht?

template<class ResultType, class... ArgTypes> 
class function<ResultType(ArgTypes......)> 
{ 
    // ... ... ... 
}; 
+0

Haben Sie eine Vorlage getestet, die so aussieht, um zu sehen, ob sie funktioniert? – Omnifarious

+1

Beide Snippets zeigen völlig verschiedene Dinge. Variadic Vorlagen werden zur Kompilierzeit behandelt. Die Variablen des Typs "C" werden zur Laufzeit behandelt. – mfontanini

+0

Die Parametersyntax '...' (nicht in der variadic-Vorlage) wird aus Gründen der Abwärtskompatibilität mit C beibehalten. Von der Verwendung wird stark abgeraten. –

Antwort

5

meine ich nicht den letzten Grund zu geben, warum die Spezialisierung nicht vorgesehen ist (ich weiß nicht, dass), aber vielleicht könnte ich auf einige der technischen Hindernisse hinweisen, die bei der Implementierung auftreten könnten. Das wird dir hoffentlich ein Gefühl geben, warum die Spezialisierung nicht da ist.

Betrachten wir zuerst, wie die std::function<> Klassenvorlage selbst implementiert werden könnte. Die Art Löschtechnik, die das Design zugrunde liegt, skizziert werden könnte wie folgt (dies ist nur eine illustrative Vereinfachung, die reale Umsetzung ist viel komplexer):

#include <memory> 

template<typename T> 
struct function { }; 

template<typename R, typename... Args> 
struct function<R(Args...)> 
{ 

public: 

    template<typename F> 
    function(F&& f) : _holder(
     new holder<typename std::decay<F>::type>(std::forward<F>(f)) 
     ) 
    { } 

    R operator() (Args&&... args) 
    { _holder->call(std::forward<Args>(args)...); } 

private: 

    struct holder_base 
    { virtual R call(Args&&... args) = 0; }; 

    template<typename F> 
    struct holder : holder_base 
    { 
     holder(F&& f) : _f(std::forward<F>(f)) { } 
     R call(Args&&... args) { return _f(std::forward<Args>(args)...); } 
     F _f; 
    }; 

    std::unique_ptr<holder_base> _holder; 
}; 

Nun wollen sie sehen, wie die Spezialisierung für Ellipsen aussehen würde, . Zuallererst sind die Anzahl und der Typ der Argumente, die für eine variadische Funktion bereitgestellt werden, nicht, die in der Signatur dieser Funktion festgelegt sind. Daher muss der Call-Betreiber unserer spezialisierten Vorlage eine Vorlage-Funktion eine beliebige Anzahl und Art der Argumente zu akzeptieren sein:

template<typename R, typename... Args> 
struct function<R(Args.......)> 
{ 
    ... 

    template<typename... Ts> 
    R operator() (Args&&... args, Ts&&... ts) 
    { _holder->call(std::forward<Args>(args)..., std::forward<Ts>(ts)...); } 

    ... 

Dies zwingt uns, die wiederum holder<> ‚s Call-Betreiber eine variadische Funktion Vorlage zu machen. Um jedoch das Löschen des Typs zu realisieren, muss derselbe Aufrufoperator virtual sein, und Funktionsschablonen können in C++ nicht virtual sein.

Die Dinge wären sicherlich einfacher, wenn variadic Argumente (ich spreche hier über Ellipsen) leicht weitergeleitet werden können, ohne zu variadischen Template-Parameter und perfekte Weiterleitung zurückzukehren. Ich bin mir jedoch nicht bewusst, dass dies auf einfache Art und Weise erreicht werden kann, und insbesondere nicht, wenn kein anderes Argument an die Funktion übergeben werden soll als diejenigen, die der variadischen Liste entsprechen.

+0

Ich denke, es gibt einige andere Ansätze, die Sie ergreifen könnten. Aber ja, die technischen Herausforderungen bei der Implementierung machen meinen Kopf weh und ich bin mir nicht sicher, ob es überhaupt sauber gemacht werden kann. – Omnifarious

+0

Sie * könnten * versuchen, ein 'va_args'-Objekt an den virtuellen' operator() (Args ..., va_args vargs) 'zu übergeben und dann versuchen, das im' holder'-Operator() 'irgendwie zu erweitern ...aber ich denke, das wäre sehr chaotisch. – Xeo

Verwandte Themen