Der folgende Code von mir sollte erkennen, ob T
begin
und end
Methoden hat:
Und hier ist ein Testcode:
%Vor% In g ++ 4.5.1 lautet die Ausgabe 1 1 1 1
. In Visual Studio 2008 lautet die Ausgabe jedoch 1 1 0 0
. Habe ich etwas falsch gemacht, oder ist das einfach ein VS 2008 Bug? Kann jemand an einem anderen Compiler testen? Danke!
Stephan T. Lavavej hat das um zu sagen:
Bitte beachten Sie, dass es technisch verboten ist, die Adresse einer Memberfunktion der Standardbibliothek zu übernehmen. (Sie können überladen werden, wodurch
&foo::bar
mehrdeutig wird und sie zusätzliche Standardargumente haben können, um Versuche zu vereiteln überstatic_cast
zu disambiguieren.)
Ich denke also, ich werde die einfachere Version verwenden, die nur nach dem verschachtelten const_iterator
-Typ sucht.
Also, hier geht es darum, diese Dinge zu debuggen.
Geben Sie zuerst die negative Alternative aus, damit Sie einen Fehler erhalten und nicht nur eine Abweichung. Als nächstes versuchen Sie, den Typ, den Sie in die Funktion einfügen, mit einem der Elemente, die nicht funktionieren, zu instanziieren.
Bei diesem Schritt konnte ich Ihr sfinae-Objekt instantiieren, aber es funktionierte immer noch nicht. Dadurch weiß ich, dass es sich um einen VS-Fehler handelt, also stellt sich die Frage, wie man es beheben kann.
VS scheint Probleme mit SFINAE zu haben, wenn Sie so behandelt werden, wie Sie sind. Es funktioniert besser, wenn Sie Ihr sfinae-Objekt einpacken. Ich habe das so gemacht:
%Vor%Hat immer noch nicht funktioniert, aber ich habe zumindest eine sinnvolle Fehlermeldung bekommen:
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'std::_Tree_const_iterator<_Mytree> (__thiscall std::set<_Kty>::* )(void) const'
Das lässt mich wissen, dass &U::end
nicht ausreicht, damit VS sagen kann, welches Ende () ich möchte. Ein static_cast behebt das:
Setzen Sie alles wieder zusammen und führen Sie Ihr Testprogramm darauf aus ... Erfolg mit VS2010. Du findest vielleicht, dass ein static_cast eigentlich alles ist, was du brauchst, aber ich habe dir das überlassen, um es herauszufinden.
Ich nehme an, die wirkliche Frage ist jetzt, welcher Compiler richtig ist? Meine Wette ist auf die eine, die konsistent war: g ++.
Bearbeiten: Jeesh ...
%Vor% Warum gehen Sie all diese Bemühungen? Wenn Sie überprüfen möchten, ob U::begin()
existiert, warum nicht versuchen?
Zusätzlich zur Überprüfung auf das Vorhandensein von U::begin()
und U::end()
wird auch überprüft, ob sie etwas zurückgeben, das in ein const_iterator
konvertierbar ist. Es vermeidet auch die von Stephan T. Lavavej hervorgehobenen Fallstricke, indem es einen Aufrufausdruck verwendet, der unterstützt werden muss, anstatt eine bestimmte Signatur anzunehmen.
[Bearbeiten] Entschuldigung, dies beruhte auf der Template-Instanziierung von VC10. Besserer Ansatz (setzt die Existenzprüfung der Argumenttypen, die tun am Überladen teilnehmen):
%Vor%Mit C ++ 11 gibt es jetzt bessere Möglichkeiten, dies zu erkennen. Anstatt sich auf die Signatur von Funktionen zu verlassen, rufen wir sie einfach in einem Ausdruck SFINAE-Kontext auf:
%Vor% Live-Beispiel auf Ideone. Die Parameter int
und long
dienen nur dazu, die Überladungsauflösung zu disambiguieren, wenn der Container beides bietet (oder wenn iterator
ist typedef const_iterator iterator
, wie std::set
erlaubt ist) - literal 0
hat den Typ int
und erzwingt die erste Überladung.
Das sollte wahrscheinlich ein Kommentar sein, aber ich habe nicht genug Punkte
@MSalters
Obwohl Ihr is_container
(fast) funktioniert und ich Ihren Code selbst verwendet habe, habe ich zwei Probleme darin entdeckt.
Erstens wird der Typ deque<T>::iterator
als Container erkannt (in gcc-4.7). Es scheint, dass deque<T>::iterator
begin
/ end
members und const_iterator
type definiert hat.
Das zweite Problem ist, dass dieser Code laut GCC-Devs ungültig ist. I qoute: -Werte von Standardargumenten sind nicht Teil des Funktionstyps und nehmen nicht an der Ableitung teil. Siehe GCC-Fehler 51989
Ich verwende derzeit dies (nur C ++ 11) für is_container<T>
:
Tags und Links c++ visual-studio-2008 stl sfinae containers