Lokale C++ Typen

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 type other_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.