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 information

    Hat 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 wie foo definiert ist, und dieser Namespace gerade nicht "in scope" ist, dann wird der operator + nicht gefunden, weil eben kein ADL passiert. In dem Fall müsstest du static_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 nicht operator + ist.


Log in to reply