Adresse eines überladenen Operators übergeben
-
Hallo,
ich wollte einfach mal aus Interesse eine Funktion wie unten schreiben, aber der GCC gibt mir einen Fehler aus:#include <iostream> template<typename T> T call(T (*func)(T, T), T number1, T number2) { return func(number1, number2); } int main() { std::cout << call((double (*)(double, double))(operator+), 4.0, 3.1) << std::endl; }
Fehlermeldung:
10:61: error: overloaded function with no contextual type informationHat jemand eine Idee, wie man das lösen kann?
-
double
ist ein eingebauter Typ, und es wäre mir neu wenn die Operatoren für eingebaute Typen Funktionen wären. Und wenn sie keine Funktionen sind, kannst du dir auch die Adresse nicht holen.Wenn es um eigene Typen geht, dann bekommst du die Adresse soweit ich weiss so:
#include <iostream> class foo {}; // eigener Typ foo operator + (foo lhs, foo rhs) // operator + für foo { return foo(); } template<typename T> T call(T (*func)(T, T), T number1, T number2) { return func(number1, number2); } int main() { std::cout << call( static_cast<foo (*)(foo, foo)>(&operator +), foo(), foo() ) << std::endl; }
ADL funktioniert hier soweit ich weiss dann auch nicht mehr, d.h. wenn der
operator +
im selben Namespace wiefoo
definiert ist, und dieser Namespace gerade nicht "in scope" ist, dann wird deroperator +
nicht gefunden, weil eben kein ADL passiert. In dem Fall müsstest dustatic_cast<ns::foo (*)(ns::foo, ns::foo)>(&ns::operator +)
schreiben.
-
Danke, ich habe mich auch schon gefragt, ob das geht. Ich hätte aber gedacht, wenn das nicht geht, käme eine etwas verständlichere Fehlermeldung .
-
Versuch mal was du für ne Fehlermeldung vom GCC bekommst wenn du
static_cast
verwendest.MSVC spuckt übrigens das aus (egal ob mit
static_cast
oder Pfui-Cast):1>UndisclosedFilename.cpp(123) : error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'double (__cdecl *)(double,double)' 1> None of the functions with this name in scope match the target type
IMO schon besser verständlich als die GCC Fehlermeldung.
-
Bei static_cast kommt so etwas ähnliches wie bei dir:
invalid static_cast from type '<unresolved overloaded function type>' to type 'double (*)(double, double)'
-
Wenn es dir nichts ausmacht, std::tr1::function (bzw. boost::function) zu verwenden - übrigens sowieso besser - dann sieht das so aus:
#include <iostream> #include <tr1/functional> template<typename T> T call(std::tr1::function<T(T,T)> func, T number1, T number2) { return func(number1, number2); } int main() { std::cout << call(std::tr1::function<double(double,double)>(std::plus<double>()), 4.0, 3.1) << std::endl; }
Mit der normalen
std::binary_function
ist sowas nicht möglich, mit Funktionspointern brauchst du eine Funktion. IMHO die einzige Möglichkeit, deinen jetzigen Code zu behalten ist selber eine Funktion add zu schreiben, die die doubles selbst addiert.template<typename T> T add(T a, T b) { return a+b; } ... call(&add<double>, 4.0, 3.1)
-
funktionär schrieb:
IMHO die einzige Möglichkeit, deinen jetzigen Code zu behalten ist selber eine Funktion add zu schreiben, die die doubles selbst addiert.
Ja, denke ich auch. Ist nicht weiter schlimm, ich wollte es ja nur einmal ausprobieren.
Danke allen!
-
funktionär schrieb:
Wenn es dir nichts ausmacht, std::tr1::function (bzw. boost::function) zu verwenden - übrigens sowieso besser - dann sieht das so aus:
#include <iostream> #include <tr1/functional> template<typename T> T call(std::tr1::function<T(T,T)> func, T number1, T number2) { return func(number1, number2); } int main() { std::cout << call(std::tr1::function<double(double,double)>(std::plus<double>()), 4.0, 3.1) << std::endl; }
Wozu
tr1::function
?#include <iostream> template <class T, class F> T call(F func, T number1, T number2) { return func(number1, number2); } int main() { std::cout << call(std::plus<double>(), 4.0, 3.1) << std::endl; }
Nur dass
std::plus
halt nichtoperator +
ist.