enable_if + disable_if Kombination provoziert einen zweideutigen Ruf
Frage
Während auf Antwort versuchen, diese Frage Ich wollte schlägt die Verwendung von enable_if
+ disable_if
der Überlastung eines Verfahren auf der Grundlage der Tatsache Rechnung zu tragen, dass ein Typ war (oder nicht) polymorph.
So habe ich eine kleine Testdatei erstellt:
template <class T>
void* address_of(T* p,
boost::enable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
boost::disable_if< boost::is_polymorphic<T> >* dummy = 0)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}
das ist ganz scheint zähmen.
Allerdings gcc (3.4 ...) Choke auf diese:
test.cpp: In Funktion
int main(int, char**)
:
test.cpp: 29: Fehler: Aufruf überladeneraddress_of(N*)
ist mehrdeutig
test.cpp: 17: Anmerkung: Kandidaten sind:void* address_of(T*, boost::enable_if<boost::is_polymorphic<T>, void>*)
[mit T = N]
test.cpp: 20: Anmerkung:void* address_of(T*, boost::disable_if<boost::is_polymorphic<T>, void>*)
[mit T = N]
Es scheint ziemlich klar zu meinem menschlichen Geist, die Überlastung sollte hier verwendet werden. Ich meine, es scheint klar, dass ich eine Alternative definiert haben und nur eine Funktion zu einem Zeitpunkt verwendet werden ... und ich hätte gedacht, dass SFINAE kümmern würde die unnötige Überlastung der ungültig zu machen.
ich gepatcht es mithilfe ...
(Auslassung) statt disable_if
und erfordern ein Dummy zweites Argument ... aber ich bin interessiert noch, warum die Compiler Drossel zu diesem Thema.
Lösung
Der Compiler gedrosselt, weil Sie die hintere ::type
auf enable_if
und disable_if
vergessen. Die Vorlagen sind immer definiert; es ist nur, dass das Mitglied type
vorhanden ist, wenn und nur wenn der Ausdruck true
(für enable_if
) oder false
(für disable_if
).
template <class T>
void* address_of(T* p,
typename boost::enable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return dynamic_cast<void*>(p); }
template <class T>
void* address_of(T* p,
typename boost::disable_if< boost::is_polymorphic<T> >::type* dummy = 0)
{ return static_cast<void*>(p); }
Ohne die Hinter ::type
, Ihre Funktion Vorlagen erstellen, Überlastungen, die Zeiger auf Instanzen von enable_if
oder disable_if
als zweiten Parameter übernehmen. Mit dem Hinter ::type
entweder die Vorlagen eine Überladung mit einem zweiten Parameter des Typ void*
erstellen oder die Überlast entfernt wird (das heißt das gewünschte Verhalten).
Andere Tipps
Mit der "Rückgabetyp" -Version von enable_if arbeitet in 3.4.4: gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_polymorphic.hpp>
#include <iostream>
template <class T>
typename boost::enable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return dynamic_cast<void*>(p); }
template <class T>
typename boost::disable_if< boost::is_polymorphic<T>, void* >::type
address_of(T* p)
{ return static_cast<void*>(p); }
struct N { int x; };
int main(int argc, char* argv[])
{
N n;
std::cout << address_of(&n) << std::endl;
return 0;
}