Ein paar Fragen für C++ 11 Experten.g ++ und clang ++ unterschiedliches Verhalten bei SFINAE und SFINAE Fehler
Ich kämpfe mit SFINAE und bin auf einen seltsamen Fall gestoßen, in dem sich g ++ (4.9.2) und clang ++ (3.5.0) anders verhalten.
Ich habe den folgenden Beispielcode vorbereitet. Es tut mir leid, aber ich kann es nicht wesentlich prägnanter machen.
#include <string>
#include <iostream>
#include <typeinfo>
#include <type_traits>
template <typename X>
class foo
{
private:
template <typename R>
using enableIfIsInt
= typename std::enable_if<std::is_same<X, int>::value, R>::type;
public:
foo()
{ }
template <typename R = void>
enableIfIsInt<R> bar()
{ std::cout << "bar: is int\n"; }
void bar()
{
std::cout << "bar: isn't int; is [" << typeid(X).name() << "]{"
<< typeid(enableIfIsInt<void>).name() << "}\n";
}
};
int main()
{
foo<long> fl;
foo<int> fi;
fl.bar();
fi.bar();
return 0;
}
Meine Idee war, eine Vorlage foo<X>
Klasse zu erstellen, die (via SFINAE) ein Verfahren, in einer oder in einer anderen Art und Weise auf dem X
Template-Argumente je definieren.
Das Programm kompiliert und mit g ++ 4.9.2 aber Klirren ++ 3.5.0 gibt die folgenden Fehler
test.cpp:13:36: error: no type named 'type' in
'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable
this declaration
= typename std::enable_if<std::is_same<X, int>::value, R>::type;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:26:23: note: in instantiation of template type
alias 'enableIfIsInt' requested here
<< typeid(enableIfIsInt<void>).name() << "}\n";
^
test.cpp:36:7: note: in instantiation of member function
'foo<long>::bar' requested here
fl.bar();
^
1 error generated.
Ich nehme an, dass Recht Klirren ist ++, aber meine erste Frage an C++ 11 Experten ist: Wer nicht wahr? g ++ oder clang ++?
über die g ++ erzeugen Programmausgabe, es ist die folgenden
bar: isn't int; is [i]{v}
so g ++ scheint die fl.bar();
Anweisung zu ignorieren.
Nun ein wenig ändern: i die zweite Version von foo<X>::bar()
auf diese Weise modifizieren
void bar()
{ std::cout << "bar: isn't int; is [" << typeid(X).name() << "]\n"; }
die std::enable_if
innerhalb der Funktion Gräuel zu löschen. Nun sind beide g ++ und Klirren ++ kompilieren, ohne Probleme und die Ausgabe für beide kompilierte Versionen des Programms ist
bar: isn't int; is [l]
bar: isn't int; is [i]
Also, meine zweite Frage ist: was ich falsch mache? Warum, in dem int
Fall, erhalte ich nicht die "is int"
Version von foo<X>::bar()
?
Haben Sie Geduld mit mir, wenn ich etwas töricht mache: Ich versuche C++ 11 zu lernen.
Und Entschuldigung für mein schlechtes Englisch.
Haben Sie versucht, dies mit einer neueren Klirren Version (wie 3.8) und ein neueres gcc (wie 5.3)? Könnte aufschlussreich sein ... –
Meist minimierte Repro: http://coliru.stacked-crooked.com/a/713fbbbca7e8b8c5. Ich beschuldige Caching. –
Berichtet als https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70642 –