Operatoren/Overloading/Templates



  • Ich sitze hier gerade vor einem ziemlich eigenartigen Problem. Nehmen wir an ich habe folgenden Code:

    template<typename A>
    class Foo
    {
    public: //
            operator A();
    };
    
    template<typename A,
             typename B>
    static A Bar(B Value);
    
    template<typename A,
             typename B>
    static A Bar(Foo<B> Value);
    

    Wie man hier sieht, hat Foo<A> einen Operatoren zur impliziten Konvertierung nach A. Die Funktion Bar<A, B> soll im Fall, dass sie zusammen mit einem Object Foo<B> anstelle eines Objektes B aufgerufen wird, anderen Code ausführen. Das Problem besteht darin, dass der Compiler nicht weiss, welche Funktion er aufrufen will. Der Quelltext zur Klasse Foo<A> darf aber nicht geändert werden. Gibt es dafür eine Lösung?



  • Mir fällt eine recht hässliche Lösung ein:

    Man erstelle sich eine simple zusätzliche Templateklasse:

    template <class T>
    class Funny
      {
      T my_intern;
      Funny<T>& operator=(const Funny<T>&);  //op== verbergen
      Funny<T>(const Funny<T>&);             //copy-ctor verbergen
    
      public:
      explicit Funny(T& arg) : my_intern(arg) {}; //macht aus einem T ein Funny<T>
      ~Funny() {};
    
      operator T() { return my_intern; } //macht aus dem funny wieder ein T
      }
    
    template<typename A,
             typename B>
    static A InnerBar(B Value);
    
    template<typename A,
             typename B>
    static A InnerBar(Foo<B> Value);
    
    template<typename A, typename B>
    static A Bar(Funny<B> Value) { return InnerBar(Value); }
    

    Auzurufen ist jetzt nur Bar. Das besondere: wenn du Bar mit Foo<X> aufrufst, dann wird erst ein Funny< Foo<X> > erstellt, und zwar Implizit. Es wird auf jedenfall kein Funny<X> erstellt, weil der Compiler nicht zwei implizite Typumwandlungen auf einmal macht, und das müsste er:
    Foo<X> --> X --> Funny<X>

    Wenn dann InnerBar aufgerufen wird, wird aus dem Funny ein Foo gemacht, aber nicht Funny -> Foo -> B, weils wieder zwei konvertierungen wären.

    Bin allerdings nicht ganz sicher ob das tut...

    Edit: alles blödsinn..
    Nein, dein Problem kann man nicht lösen, weil das B aus dem ersten Template ja genausogut ein Foo<X> sein könnte. stell dir mal vor, was passieren soll, wenn jemand Bar(Foo< Foo< Foo<X> > >) aufruft... dann ist eben B = Foo< Foo< Foo<X> > >


  • Mod

    template<typename A,
             typename B>
    static A Bar(Foo<B> Value);
    

    wenn ich das richtig sehe, kann die funktion ohnehin nur qualifiert aufgerufen werden, denn A kann der compiler nicht aus dem aufruf herleiten. eine spezialisierung für Foo<B> fällt ebenfalls aus, denn partielle spezialisierungen sind für funktionen nicht möglich.


Anmelden zum Antworten