[SFINAE] Compile error mit std::enable_if und std::is_arithmetic
-
Hi, ich wollte eine Funktion mittels SFINAE so überladen, dass sie alle arithmetischen Typen akzeptiert. Mein Ansatz sieht wie folgt aus:
#include <type_traits> #include <iostream> void foo(std::string const & value) { std::cout << value << " is a string\n"; } template <class T> void foo(typename std::enable_if<std::is_arithmetic<T>::value, T>::type value) { std::cout << value << " is arithmetic\n"; } int main() { foo("hallo welt"); foo(124); foo(34.5); }
Allerdings lande ich mit clang 3.5 in einer Sackgasse:
test.cpp:15:5: error: no matching function for call to 'foo' foo(124); ^~~ test.cpp:4:6: note: candidate function not viable: no known conversion from 'int' to 'const std::string' (aka 'const basic_string<char>') for 1st argument void foo(std::string const & value) { ^ test.cpp:9:6: note: candidate template ignored: couldn't infer template argument 'T' void foo(typename std::enable_if<std::is_arithmetic<T>::value, T>::type value) { ^
Mit GCC 4.8 läuft es ähnlich - nur weniger aussagekräftig.
Habe ich irgendwo einen Denk-/Tippfehler - oder sind CLANG und GCC diesbezüglich noch nicht so weit? Prinzipiell sollte die Argumentliste für arithmetische Typen well-formed und für sonstige Typen ill-formed sein, so dass ich dank SFINAE unter'm Strich meine Funktion für alle arithmetischen Typen überladen habe(n müsste).. ^^
LG Glocke
-
template <class T> void foo(typename std::enable_if<std::is_arithmetic<T>::value, T>::type value)
Weiter habe ich gar nicht geschaut. Der Fehler fällt sofort ins Auge: Der Parametertyp ist ein non-deduced context, d.h. Template-Argumente werden dafür nicht deduziert. Mach einfach
template <class T> typename std::enable_if<std::is_arithmetic<T>::value>::type foo(T value)
draus.
-
Glocke schrieb:
Habe ich irgendwo einen Denk-/Tippfehler
ja. Das enable_if-Konstrukt kann nicht dazu hergezogen werden, das Templateargument zu deduzieren.
Es wird immer ein Argument benötigt, aus dem heraus eine Deduktion möglich it, und enable_if taucht an anderer Stelle auf (weiteres Funktionsargument, Rückgabetyp oder zus. Templateparameter) so dass bei einem unzulässigen (bereits deduzierten) Templateparameter die Deklaration ungültig wird.
-
Arcoth schrieb:
template <class T> typename std::enable_if<std::is_arithmetic<T>::value>::type foo(T value)
Ok danke, das funktioniert erstmal
Aber dabei scheint mein Return type verloren zu gehen, oder? Angenommen ich möchte einen bool liefern.. wie genau müsste ich die Signatur dann verändern?
/EDIT: Also geht das nicht? XD Welche Möglichkeiten bleiben mir dann?
-
template <class T> typename std::enable_if<std::is_arithmetic<T>::value, bool>::type foo(T value)
Siehe auch die Referenz zu
enable_if
.
-
enable_if hat einen zweiten Templateparameter.
-
Arcoth schrieb:
template <class T> typename std::enable_if<std::is_arithmetic<T>::value, bool>::type foo(T value)
Siehe auch die Referenz zu
enable_if
.Danke, irgendwie hab ich das in der Dokumentation wohl überlesen
thx - kann geschlossen werdenLG Glocke