std::enable_if zum bedingten kompilieren einer member-Funktion
Ich versuche ein einfaches Beispiel zu arbeiten, um zu verstehen, wie std::enable_if
. Nachdem ich gelesen diese Antwort, dachte ich, es sollte nicht allzu schwer zu kommen mit einem einfachen Beispiel. Ich will std::enable_if
zu wählen zwischen zwei member-Funktionen und dass nur einer von Ihnen verwendet werden.
Leider die folgenden nicht kompilieren mit gcc 4.7 und nach Stunden und Stunden zu versuchen, bitte ich Euch, Jungs, was mein Fehler ist.
#include <utility>
#include <iostream>
template< class T >
class Y {
public:
template < typename = typename std::enable_if< true >::type >
T foo() {
return 10;
}
template < typename = typename std::enable_if< false >::type >
T foo() {
return 10;
}
};
int main() {
Y< double > y;
std::cout << y.foo() << std::endl;
}
gcc-berichten die folgenden Probleme:
% LANG=C make CXXFLAGS="-std=c++0x" enable_if
g++ -std=c++0x enable_if.cpp -o enable_if
enable_if.cpp:12:65: error: `type' in `struct std::enable_if<false>' does not name a type
enable_if.cpp:13:15: error: `template<class T> template<class> T Y::foo()' cannot be overloaded
enable_if.cpp:9:15: error: with `template<class T> template<class> T Y::foo()'
Warum nicht g++ löschen Sie den falschen-Instanziierung für die zweite member-Funktion? Laut Norm std::enable_if< bool, T = void >::type
nur dann existiert, wenn die boolschen template-parameter true ist. Aber warum nicht g++ betrachten dies als SFINAE? Ich denke, dass die überlastung Fehlermeldung kommt das problem, dass g++ nicht löschen die zweite member-Funktion, und ist der Auffassung, dass dies eine überlastung.
Ich dachte das auch und habe
std::is_same< T, int >::value
und ! std::is_same< T, int >::value
gibt das gleiche Ergebnis.InformationsquelleAutor evnu | 2011-08-07
Du musst angemeldet sein, um einen Kommentar abzugeben.
SFINAE funktioniert nur, wenn die substitution im argument der Abzug von template-argument macht das Konstrukt schlecht ausgebildet. Es gibt keine solche substitution.
Das ist, weil, wenn der Vorlage-Klasse instanziiert wird (was passiert, wenn Sie erstellen ein Objekt vom Typ
Y<int>
zu anderen Fällen), instanziiert es alle seine member-Deklarationen (nicht unbedingt zu Ihren Definitionen und/oder Einrichtungen!). Unter Ihnen sind auch seine Mitglied-Vorlagen. Beachten Sie, dassT
bekannt ist, und dann!std::is_same< T, int >::value
ergibt false. Also wird es eine KlasseY<int>
enthältDen
std::enable_if<false>::type
Zugriff auf einen nicht vorhandenen Typ, also, die Erklärung ist schlecht ausgebildet. Und damit Ihr Programm ist ungültig.Müssen Sie dem betreffenden Vorlagen'
enable_if
hängt von einem parameter des betreffenden Vorlage selbst. Dann gelten die Erklärungen, weil der ganze Typ ist immer noch abhängig. Wenn Sie versuchen, rufen Sie einen von Ihnen, argument-Abzug Ihrer Vorlage Argumenten geschehen, und SFINAE passiert, wie erwartet. Sehen diese Frage und die entsprechende Antwort, wie das zu tun.Y
template-Klasse instanziiert wird, wird der compiler nicht eigentlich das template member-Funktionen, aber der compiler führt die substitution vonT
in dem betreffenden template-DEKLARATIONEN so, dass diese member-templates instanziiert werden können, zu einem späteren Zeitpunkt. Diese Fehlerquelle ist nicht SFINAE, weil SFINAE gilt nur, wenn die Bestimmung der Menge der möglichen Funktionen für überlast-Auflösung, und instantiieren einer Klasse ist nicht ein Fall der Feststellung einer Reihe von Funktionen für überlast Auflösung. (Oder so denke ich!)InformationsquelleAutor Johannes Schaub - litb
Ich aus diesem kurzen Beispiel, welches auch funktioniert.
Kommentar, wenn Sie möchten mir zu aufwendig. Ich denke, der code ist mehr oder weniger selbsterklärend, aber dann wieder, ich machte es so, ich könnte falsch sein 🙂
Sehen Sie es in Aktion hier.
error C4519: default template arguments are only allowed on a class template
.Das ist bedauerlich. Ich habe nur getestet mit gcc. Vielleicht hilft das: stackoverflow.com/a/17543296/660982
dies ist sicherlich die beste Antwort hier-und genau das, was ich suchte.
Warum es notwendig ist, erstellen Sie einen anderen Vorlage-Klasse
Q
, obwohl es gleichT
?Da müssen Sie die Vorlage der
test
member-Funktion. Beide können nicht zur gleichen Zeit existieren.Q
nur leitet der Vorlage-Klasse TypT
. Sie können der Vorlage-KlasseT
etwa so: cpp.sh/4nxw, aber diese Art von Niederlagen der Zweck.InformationsquelleAutor jpihl
Für diejenigen, die spät-Ankömmlinge, die auf der Suche nach einer Lösung, die "einfach funktioniert":
Kompilieren mit:
Laufen gibt:
std::enable_if_t
zuresolvedType
.InformationsquelleAutor user1284631
Vom diese post:
Aber man kann etwas wie das hier tun:
class std::enable_if.....
solltetypename std::enable_if.....
InformationsquelleAutor Janek Olszak
Einen Weg, um dieses problem zu lösen, Spezialisierung von member-Funktionen ist die Spezialisierung in eine andere Klasse, dann Erben von dieser Klasse. Sie müssen möglicherweise ändern Sie die Reihenfolge der inheritence, erhalten Sie Zugriff auf alle anderen zugrunde liegenden Daten aber diese Technik funktioniert.
Der Nachteil dieser Technik ist, dass, wenn Sie brauchen, um zu testen, eine Menge verschiedener Dinge für verschiedene member-Funktionen haben Sie, um eine Klasse für jeden, und die Kette die es in der inheritence tree. Dies gilt für den Zugriff auf gemeinsame Daten Mitglieder.
Ex:
InformationsquelleAutor Gary Powell
Den booleschen muss, hängt von der template-parameter abgeleitet. Also ein einfacher Weg, das zu beheben, ist die Verwendung eines Standard-boolean parameter:
Jedoch, das wird nicht funktionieren, wenn Sie wollen, um eine überlastung der member-Funktion. Stattdessen, seine besten verwenden Sie
TICK_MEMBER_REQUIRES
aus der Tick Bibliothek:Können Sie auch schreiben Sie Ihre eigenen Mitglied zu werden, muss die makro wie folgt aus(nur für den Fall, Sie nicht möchten, dass die Verwendung einer anderen Bibliothek):
Das Beispiel funktioniert nicht mit überlastung. Ich aktualisiert meine Antwort, wie Sie es tun, mit überlastung.
InformationsquelleAutor Paul Fultz II