Mehrdeutige Funktionsnamen auflösen



  • Hallo Forum,

    folgende Frage. Nehmen wir an, ich hätte zwei freie Konvertierungsfunktionen, die Objekte vom Typ A in Typ B konvertieren und umgekehrt. Da die Signatur unterschiedlich ist, kann ja prinzipiell der Funktionsname identisch sein.

    struct A {};
    struct B {};
    
    A Convert(const B& b)
    {
       return A();
    }
    
    B Convert(const A& a)
    {
       return B();
    }
    

    Wenn ich nun diese Convert-Funktionen z.B. in einem Algorithmus der Standard-Library benutzen möchte, ist mir nicht ganz klar, wie ich die Mehrdeutigkeit des Namens auflösen kann.

    B Foo(const A& a)
    {
       return B();
    }
    
    int main()
    {
       std::vector<A> aVec(3, A());
       std::vector<B> bVec(aVec.size());
    
       std::transform(aVec.cbegin(), aVec.cend(), bVec.begin(), &Foo);               // (1) funktioniert, Name eindeutig
    
       // std::transform(aVec.cbegin(), aVec.cend(), bVec.begin(), &Convert);        // (2) funktioniert nicht, Name nicht eindeutig
    
       std::transform(aVec.cbegin(), aVec.cend(), bVec.begin(), [](const auto& val)  // (3) funktioniert ebenfalls, weil der Typ A bereits "deduziert" wurde.
       {
          return Convert(val);
       });
    
        return 0;
    }
    

    Gibt es eine elegantere/bessere Möglichkeit als (3), wenn ich die Funktionen nicht eindeutig benennen möchte?

    Vielen Dank vorab!


  • Mod

    Zuallererst möchte ich darauf hinweisen, dass das forwarden eines Namens ein interessantes Feature wäre. Ich habe mich ein wenig damit beschäftigt, aber dann IIRC ein Paper gefunden, also nichts weiter in der Richtung verfasst. Idealerweise könnten wir einen Namen mit @ o.ä. qualifizieren, und damit den Templateparameter als eine art Proxy deduzieren lassen, der den Namen ad-hoc auflöst.

    Das kann man auch über ein Makro erledigen:

    #define FORWARD(X) [] (auto&&... args) {return X(std::forward<decltype(args)>(args)...);}
    

    Falls das zu rustikal erscheint, kann man auch ein Template einsetzen, das mittels des gegebenen Parametertypen die Funktion auswählt.



  • Das ist vermutlich das Einfachste:

    static_cast<A (*)(const B& b)>(&Convert);
    


  • Autor Nachricht Skylac06 schrieb:

    static_cast<A (*)(const B& b)>(&Convert);
    

    Danke für den Hinweis, kam mir nicht unmittelbar in den Sinn. Wirklich schön liest sich der Function-Pointer-Cast zwar nicht, erfüllt aber seinen Zweck.

    Arcoth schrieb:

    #define FORWARD(X) [] (auto&&... args) {return X(std::forward<decltype(args)>(args)...);}
    

    Das Makro ist quasi ein "universelles" Lambda, das per Perfect-Forwarding die Argumente an die eigentliche Funktion weitergibt? Also im Prinzip eine allgemeine Form dessen, was ich unter (3) geschrieben habe, inklusive Forwarding?
    Interessant, aber ich muss zugeben, dass ich sowas nicht eben mal so hinschreibe.


Log in to reply