VC11 Compiler
-
Hallo!
Ich habe heute mal die Developer Preview der VC11 installiert und getestet und habe mit Freuden festgestellt, dass der std::function<>-Bug behoben wurde, welcher es verhindert hatte, dass sich function<> nicht an Funktionen oder Funktoren mit Rvalue-Referenzen als Parameter binden konnte. Wenn ich nun aber folgendes probiere:#include <functional> #include <iostream> void a(int a, int i, int&& x) { // do something } void fun(std::function<void (int, int&&)> func) { func(12, 11); } int main() { fun(std::bind(a, 12, std::placeholders::_1, std::placeholders::_2)); std::cin.get(); }
Dann meckert mich der Compiler wieder voll. Ist das ein weiterer Bug in der VC-Stdlib oder hab ich mich irgendwo vertan?
-
g++ und clang++ meckern zwar über ungebrauchte Parameter, kompillieren deinen Code ansonsten jedoch ohne Probleme (Parameter: -Wall -Wextra -pedantic -std=c++0x).
Also ziemlich sicher ein Bug.
-
Jodocus schrieb:
Dann meckert mich der Compiler wieder voll.
Sieht nach Microsoft Bug aus. Ohne Fehlermeldung kann man den Schuldigen aber schlecht ausmachen. Bei std::function und/oder std::bind ist der Wurm drin.
Der Compiler unterstützt immer noch keine variadischen Templates. Das macht die Implementierung von std::function und std::bind schon sehr … ähm … hässlich. Es wundert mich gar nicht, dass das noch nicht 100%ig funktioniert.
Mach'n ausführlichen Bugreport und schick ihn an MS.
-
krümelkacker schrieb:
Mach'n ausführlichen Bugreport und schick ihn an MS.
Und wenn du sie mobben willst fragst du ganz nebenbei noch nach variadic Templates.
-
Done. Was Variadic Templates angeht: Ich hab kürzlich gelesen, dass die STL-Entwickler wohl um Variadic Templates flehen, da es performancetechnisch wohl ganz schön abwerts geht mit der MS-Stdlib im Vergleich zu anderen Compilern. Aber (wen wundert's) wie immer landet das Budget nicht bei der Kompatibilität zum Standard. War ja mit VS 6 wohl nicht viel anders.
Edit: Wenn ihr alle brav mit auf den "Ich kann's reproduzieren"-Button drückt, setzten sie sich vielleicht ran. Wünschenswert wäre es ja.
-
cooky451 schrieb:
krümelkacker schrieb:
Mach'n ausführlichen Bugreport und schick ihn an MS.
Und wenn du sie mobben willst fragst du ganz nebenbei noch nach variadic Templates.
Och wieso, geht doch auch ohne!
_VARIADIC_EXPAND_0X(_CLASS_BIND, , , , ) // <------ LOL! #define _VARIADIC_EXPAND_25(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_2(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_3(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_4(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_5(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_26(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_25(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_6(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_27(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_26(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_7(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_28(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_27(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_8(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_29(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_28(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_9(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_2A(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_29(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_10(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_ALT_05(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_0(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_1(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_2(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_3(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_4(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_5(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_ALT_06(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_05(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_6(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_ALT_07(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_06(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_7(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_ALT_08(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_07(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_8(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_ALT_09(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_08(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_9(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_ALT_0A(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_09(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_ALT_A(FUNC, X1, X2, X3, X4) // for 0-X args #define _VARIADIC_EXPAND_0X(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_0(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_1X(FUNC, X1, X2, X3, X4) #define _VARIADIC_EXPAND_1X(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_1(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_2X(FUNC, X1, X2, X3, X4) // for extra list, one element shorter #define _VARIADIC_EXPAND_P1_0(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_0(FUNC, X1, X2, _RAW_LIST0, ) \ #define _VARIADIC_EXPAND_P1_1(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_1(FUNC, X1, X2, _RAW_LIST0, ) \ #define _VARIADIC_EXPAND_P1_25(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_2(FUNC, X1, X2, _RAW_LIST1, _COMMA) \ _VARIADIC_EXPAND_3(FUNC, X1, X2, _RAW_LIST2, _COMMA) \ _VARIADIC_EXPAND_4(FUNC, X1, X2, _RAW_LIST3, _COMMA) \ _VARIADIC_EXPAND_5(FUNC, X1, X2, _RAW_LIST4, _COMMA) #define _VARIADIC_EXPAND_P1_26(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_P1_25(FUNC, X1, X2, X3, X4) \ _VARIADIC_EXPAND_6(FUNC, X1, X2, _RAW_LIST5, _COMMA)
-
Nett. Aber es wird eigentlich noch witziger wenn man die Story dazu kennt. Microsoft hat scheinbar erfragt welches C++11 Feature wohl am beliebtesten sei und ist dann auf variadic Templates gekommen. Dann haben sie versucht das zu implementieren, aber sind wohl leicht an der Performance gescheitert. Und jetzt haben sie mit VS11 weder variadic Templates, noch viele kleine andere Features. Aber angeblich soll das ja nachgeliefert werden.
-
Tja, bleibt die Frage, wie ich das mit dem VC-Compiler umschiffen kann. Ich suche eigentlich eine Lösung ohne Smart Pointer, da ich die Rvalue-Referenzen da sehr mag. Hat jemand 'ne Idee?
-
Erklär doch mal, warum Du überhaupt eine Rvalue-Referenz verwendest. Das sieht nämlich ein bissel komisch aus. Vielleicht kann man das wirklich ganz anders besser lösen.
-
Mit Lambdas lässt sich std::bind oft vermeiden.
Unabhängig von deinem Problem, leitet std::bind die gebundenen Argumente nur als lvalues weiter, daher passen die Move-Sematik und std::bind nicht so gut zusammen.#include <iostream> #include <functional> void innerfun(int a, int&& b) { std::cout << a << " " << b << '\n'; } template <typename Callable> void outerfun(Callable && c) { c(12); } int main() { outerfun([](int i){ innerfun(11,std::move(i));}); return 0; }
-
krümelkacker schrieb:
Erklär doch mal, warum Du überhaupt eine Rvalue-Referenz verwendest. Das sieht nämlich ein bissel komisch aus. Vielleicht kann man das wirklich ganz anders besser lösen.
z.B. für eine Callback-Funktion nach einem Socket-accept(). Der neue, nicht-kopierbare Socket soll der Funktion als Parameter übergeben werden.
@ einwurf:
Sieht interessant aus, das schau ich mir mal an, danke! Es müsste für std::bind neben std::ref() und std::cref() auch ein std::rref() oder so geben, dann würde es klappen, oder?
-
Hehe, ich sah gerade:
http://channel9.msdn.com/shows/Going+Deep/Stephan-T-Lavavej-Everything-you-ever-wanted-to-know-about-nullptr/Der Herr (dessen Initialisien S.T.L. sind :D) implementiert die STL für MS. Und er sagt, dass er in den Hungerstreik gehen will, falls Variadic Templates nach VS10 nicht implementiert werden. Ich wette, er ist verhungert.
-
Visual Studio 2011 ist ja noch nicht offiziell erschienen, oder? Ist denn definitiv, dass die endgültige Version (wird die immer noch 2011 heissen?) keine Variadic Templates haben wird?
-
Jodocus schrieb:
z.B. für eine Callback-Funktion nach einem Socket-accept(). Der neue, nicht-kopierbare Socket soll der Funktion als Parameter übergeben werden.
Und was macht die damit? Warum ist es ein Rvalue-Referenzparameter? Das hast Du immer noch nicht verraten.
Jodocus schrieb:
Es müsste [...] neben std::ref() und std::cref() auch ein std::rref() oder so geben, dann würde es klappen, oder?
Killefit.
Das riecht echt nach Rvalue-Referenz-Fehlbenutzung alles.
Zeig mal mehr Code. Erklär mal mehr.
-
> Und was macht die damit? Warum ist es ein Rvalue-Referenzparameter? Das hast Du immer noch nicht verraten.
Es ist ein Rvalue-Referenzparameter, weil der Socket innerhalb der Library erstellt wird und dem User zur Verfügung gestellt werden soll, sprich auch außerhalb der Library verwendet werden muss. Hier die Optionen:
Kopieren: Unmöglich, da einzigartige Resource und Desaster beim Multithreading, wenn die Resource freigegeben wird.
Referenz: Das bedeutet, dass die Library selbst die Ressourcen speichern muss und dem Client lediglich Referenzen darauf gibt. Allerdings gibt's dann keine Chance die Ressource zeitnah wieder freizugeben, es sei denn, man teilt es der Library explizit mit (á la
delete_resource(...)
) und das wäre recht hässlich.Pointer: Zu hässlich. Nicht exceptionsicher.
Smart-Pointer: Bisherige Lösung. Einzig der shared_ptr<> funktioniert damit erfolgreich, da er kopiert werden kann, dabei aber die Resource nicht kopiert. Als Notlösung wollte ich unique_ptr verwenden, da ein shared_ptr<> eigentlich nicht ganz das ausdrückt, was ich will. Aber der kann dank Rvalue-Referenz-Bugs auch nicht benutzt werden.
Rvalue-Referenzen: Eleganteste Methode. Die Library erstellt die Resource, gibt sie per Move an den Client als Stackvariable und räumt sich von alleine auf, wenn sie nicht mehr gebraucht wird. Leider dank Visual Studio Bugs nicht möglich.
Edit: @ Nexus: Sie versprachen noch vor der Veröffentlichung von VS 2010, dass Variadic Templates auf Platz 1 der Prioritätsliste sitzt, aber schafften es für VS 10 nicht. Nun ist das erste VS 11 da und die Variadics sind wieder nicht dabei. Siehe: http://connect.microsoft.com/VisualStudio/feedback/details/463677/support-variadic-templates
Intern heißt es wohl, dass sie es wieder und wieder versucht haben, aber daran scheiterten. Wenn es Intel und GCC schaffen, wieso sollte es MS nicht hinbekommen?
Bzgl. dem VS-Namen: Dass Visual Studio 10.0 auf das Jahr 2010 fiel, ist Zufall. 10 ist die Versionsname, 2010 der Produktname. Das nächste VS wird definitiv die Version 11.0 sein, als Produktname rate ich 2012 - mit der Veröffentlichung von Windows 8.
-
Jodocus schrieb:
Kopieren: Unmöglich, da einzigartige Resource und Desaster beim Multithreading, wenn die Resource freigegeben wird.
Verstehe ich immer noch nicht so ganz:
void foo(Socket socket) { } int main() { Socket socket; foo(std::move(socket)); }
Warum funktioniert das Vorgehen bei dir nicht?
-
Nene cooky, so einfach ist das nicht.
Es handelt sich dabei um einen asynchronen Callback. Der kommt sogar aus einem anderen Thread. Das Ziel ist das:void callback(socket&& sock) { // bla } int main() { start_accept(callback); }