Überladen von Funktionen?



  • Ich möchte zwei Funktionen überladen:

    typedef unsigned __int64 bitboard_t;
    
    inline bitboard_t file_bitboard(const int file) {  // 0 <= file <= 7
      return file_bb[file];
    }
    
    inline bitboard_t file_bitboard(const int square) {  // 0 <= square <= 63
      return file_bb[square_file(square)];
    }
    

    Beide Funktionen sind zeitkritisch und es kann kein zusätzlicher Code für eine Fallunterscheidung zur Laufzeit eingebaut werden. Ich möchte überladen, ohne einen neuen Datentypen via Enumeration zu definieren. Was habe ich noch für Möglichkeiten - so wie oben kann es natürlich nicht gehen?

    Ich schätze mal das geht auch nicht (habs noch nicht ausprobiert, klingt aber unsinnig):

    typedef int file_t;
    typedef int square_t;
    typedef unsigned __int64 bitboard_t;
    
    inline bitboard_t file_bitboard(const file_t file) {  // 0 <= file <= 7
      return file_bb[file];
    }
    
    inline bitboard_t file_bitboard(const square_t square) {  // 0 <= square <= 63
      return file_bb[square_file(square)];
    }
    

  • Mod

    Du musst eine Wrapperklasse, keinen typedef, für int machen, um die beiden Funktionen unterscheiden zu können.

    Ich habe aber den Eindruck, dass du Überladung hier falsch einsetzen willst. Kannst du etwas mehr Kontext zu deinem Problem geben?



  • Kontext:

    Ich baue eine Schachengine und benötige eine 64-Bit Bitmaske für die Linien A-H auf dem Schachbrett. Die Funktionen sollen deshalb überladen werden, damit ich eine Bitmaske für die entsprechende Linie A-H bekomme, egal ob ich der Funktion ein Feld (0-63) oder eine Linie (0-7) übergebe.

    Ich weiss, dass ich hier nicht überladen müsste (logisch aber unsauber). Aber spätestens bei den Reihen muss ich das tun.

    Jetzt bin ich Anfänger und weiss leider auch nicht genau, was eine Wrapper-Klasse ist? Und die Performance ist auch entscheidend, da laut Profiler diese Funktionen extrem oft aufgerufen werden und relativ viel CPU-Zeit konsumieren.

    Danke schonmal 🙂



  • > return file_bb[file];

    Ich kann mir nicht vorstellen, dass das CPU-Zeit kosten sollte. Mit Wrapper ist z.B. das gemeint:

    class file {
    private:
       int f;
    
    public:
       file(int file) : f(file) { } // Hier gleich Wertebereich usw. einschränken
       int get() { return f; }
    };
    
    // ...
    
    inline bitboard_t file_bitboard(const file f) {
      return file_bb[f.get()];
    }
    
    // ...
    
    file_bitboard(4);
    


  • Ok. Wenn das die einzige Möglichkeit ist, dann lasse ich es erstmal wie es ist und verzichte auf die Überladung. Muss dann halt mehr aufpassen.

    Achja, und danke 🙂



  • Also da gibt es durchasus ein paar Möglichkeiten. Die erste Variante einer Wrapper Klasse wurde genannt. Das kannst du ganz einfach so machen:

    struct file_t
    {
     int value;
    };
    
    struct square_t
    {
     int value;
    };
    

    Die beiden Klassen wrappen (umschliessen) den int und Stellen so neue Typen dar. Du musst den Zugriff einfach ein wenig abändern. Das sollte sogar soweit optimiert werden können, dass da gar kein anderer Code generiert wird, als wenn du direkt int's genommen hättest.

    Dann eine weitere Möglichkeit wäre ja die Funktionen einfach anders zu benennen.

    Dann könntest du auch noch einen dummy Parameter einbauen, der halt einen anderen Typen hat je nach Funtion (da würde ich aber eher zum Umbenennen der Funktion tendieren).

    Aber ich bezweifle auch mal, dass dein Programm (im Endstadium) dort wirklich einen Engpass haben wird. Wenn ich an eine Schachengine denke, dann denke ich eher weniger an die paar Zugriffe, die aufs Spielfeld gemacht werden, sondern eher an die Berechnungn, die ablaufen, um den nächsten Zug zu berechenen, wo ich einen enorm viel höheren Optimierungsbedarf sehe.


Log in to reply