Lokale C++ Typen
« | 27 Feb 2022 | »Compiler Experimente mit älteren Varianten des GCC haben mir leider einen Workaround zerschossen, den ich als Abstraktion und Ersatz von Lambda Ausdrücken vorgesehen hatte:
Nämlich den Einsatz von lokalen Typen.
Konkret: Klassen, die innerhalb einer Funktion deklariert werden.
Wenn der GCC nämlich einen Fehler wie folgt produziert:
error: template argument for
some_function(...)
uses local typeother_function::class_name
Wurde ein Fall ausgelöst, den Microsofts MSVC offenbar immer schon ignoriert hatte und der beim GCC mit der Aktivierung von C++11 entschärft wurde.
Auf stackoverflow.com
wurde auch schon die Erklärung präsentiert: Man darf nämlich solche lokalen
Typen nicht in Templates benutzen.
Dort schlägt dann nämlich die Typenableitung fehlt.
Bisher war mir das nicht aufgefallen, da meine Testkompilate immer mit
GCC Varianten >= 6
erfolgten, doch mit einem GCC 5 wird der Fehler
sofort sichtbar.
Mit C++11 wurde (vermutlich eben genau wegen Lambdas und auto
) diese Regel
gelockert, wovon bei den neueren GCCs offenbar auch die älteren C++ Standards
berührt werden.
Die “schnelle” Lösung sieht also so aus, dass beim GCC C++11 immer aktiviert ist.
In CMAKE kann man das entweder mit der
Variable CMAKE_CXX_STANDARD=11
(ab CMAKE 3.1) erreichen, oder indem man den
CMAKE_CXX_FLAGS
einfach ein -std=gnu++11
anhängt.
Doch genau das führt jetzt meine ursprüngliche Implementierung teils ad
absurdum und macht sie zu einer reinen MSVC-only Lösung.
Denn mit C++11 werden Lambdas im Sprachstandard aktiviert und somit kommt
mein Workaround mit Makros und lokalen Klassen gar nicht zu Einsatz.
Und somit fällt die Kompatibilität zu noch älteren GCCs ohne C++11 vollständig weg, was ich eigentlich nicht wollte.
Fazit
Tja … zu früh gefreut. Oder?
Ich bin mir jetzt noch nicht sicher, wie ich mit der Erkenntnis umgehen soll. In Sachen Kompatibilität ist mein Anspruch in Richtung Microsoft weitreichender, als das unter Linux der Fall wäre.
Mit WinCE bleibt der
MSVC 2005 nach wie vor ein “notwendiger” Compiler für mich, wo der
Workaround funktioniert.
Aber antike Linux-Systeme mit C++98/03 von vor über 10 Jahren muss ich (aktuell)
nicht supporten … von daher kann ich mich vorläufig auf der erzwungenem C++11
Konfiguration ausruhen.
Zumindest habe ich nun eine Erklärung dafür gefunden, warum z.B. boost Lambdas auch nie über lokale Typen implementiert hat.
Und die Moral von der Geschicht’:
Buggy-Compiler erlauben vieles.
Aber standard-konforme eben nicht.