Lambdas sind lediglich automatisch geschriebene aufrufbare Objekte, um einfachen Code einfach zu machen. Wenn Sie etwas über ihr automatisches Standardspeicherverhalten hinaus möchten, schreiben Sie den Typ, den sie selbst schreiben.
Es ist illegal, einen Lambda-Typ in einem unbewerteten Kontext zu haben. In einem evaluierten Kontext erstellt es ein Lambda im automatischen Speicher. Sie wollen es im kostenlosen Geschäft. Dies erfordert zumindest logisch eine Kopie.
Eine schreckliche Hack Einbeziehung der unevaluierten Kontextregel verletzen, sizeof/alignof, aligned_storage_t, Platzierung neuer, möglicherweise unbegrenzt Kompilierung Rekursion (oder vielleicht auch eines mit einem static_assert
), Zeiger auf lokale Variablen und der Aliasing-Konstruktor der gemeinsamen ptr Rückkehr und wenn Anrufer wahnsinnigen Code schreiben müssen, könnte dies den Aufruf von copy/move verhindern. Aber es ist eine schlechte Idee und einfach aufrufbare Objekte zu verwenden ist einfacher.
Natürlich akzeptiert das Kopieren/Verschieben es trivial. Aber an diesem Punkt verwenden Sie einfach std::function
, es sei denn, Sie benötigen etwas wie Varargs.
Sie geben an, dass Benutzer nicht gezwungen werden sollen, std::function
zu verwenden; aber std::function
würde implizit ein kompatibles Lambda in sich selbst umwandeln.
Wenn Sie bereit sind, eine Kopie zu übernehmen, können wir dies tun:
template<class T>
std::shared_ptr<std::decay_t<T>>
auto_shared(T&& t) {
return std::make_shared<std::decay_t<T>>(std::forward<T>(t));
}
dann auto ptr = auto_shared([x=0]()mutable{ return x++; });
ist ein nicht-Typ-gelöschten freigegebenen Zeiger auf eine Zählung Lambda. Das Lambda wird kopiert (also verschoben) in den gemeinsamen Speicher. Wenn Sie diese Kopie vermeiden möchten, kann der Client ein manuelles Funktionsobjekt schreiben und make_shared<X>(ctor_args)
darauf aufrufen.
Es gibt keinen vernünftigen Weg, einen lambdas-Typ von seiner Konstruktion in C++ zu trennen.
Sie versuchen, lambdas zusammen mit intelligenten Zeigern in einer Weise zu verwenden, die wirklich keinen Sinn macht, das wäre so viel einfacher, wenn Sie 'std :: function' stattdessen verwenden würden. Sie * verwenden * den intelligenten Zeiger IMO als Ressourcen-Wrapper anstatt nur einen einfachen selbstlöschenden Zeiger.Wie für die "extra indirection" von "std :: function", wird das wirklich ein Engpass in Ihrem Code sein? Es ist nicht mehr eine zusätzliche Umleitung, als mit intelligenten Zeigern wirklich, und mit 'std :: function' haben Sie eine schönere und viel sauberere Syntax, sowohl beim Einrichten als auch beim Verwenden/Aufrufen der Funktion. –
http://coliru.stacked-crooked.com/a/997216714e0e7d74 –
Oh, und die Verwendung von 'std :: function' beschränkt Sie nicht nur auf lambdas, was ist, wenn die Leute Ihren Code pflegen oder anderweitig Ihren Code verwenden , möchte eine Nicht-Lambda-Funktion verwenden? Mit eigenen "Smart Function Pointer" -Typen ist das nicht möglich. Da jedes Lambda einen eindeutigen Typ hat, kann der gemeinsame Zeiger außerdem nur für das spezifische Lambda und kein anderes Lambda mit der gleichen Signatur verwendet werden. –