Home > Software design >  What is this "operator" block of code in c class
What is this "operator" block of code in c class

Time:04-19

I'm using someone's class for bitmaps, which are ways of storing chess positions in 64-bit bitsets. I was wondering what the part with auto() operator does. Is "auto" used because it returns one bit, which is why a return-type isn't specified for the function? I get that it checks that x and y are in the bounds of the chess board, and asserts an error if they aren't. I also understand that it returns a bit that corresponds to the x,y value pair for the bitset. I also don't get why the function is defined like it is, with an extra pair of parentheses. Any help is appreciated!

class BitBoard {
    private:
        std::bitset<64> board;
    public:
        auto operator()(int x, int y) {
            assert(0<=x && x<=7);
            assert(0<=y && y<=7);
            return board[8*y x];
        }
    }
};

CodePudding user response:

The "extra" pair of parentheses are because you're defining operator(), which lets instances of your class behave like functions. So if you had a:

BitBoard board;

you could get the value for x=3, y=5 by doing:

board(3, 5)

instead of having a method you call on the board explicitly, like board.get_bit_as(3, 5).

The use of auto just means it deduces the return type from std::bitset<64>'s operator[]; since the method isn't const qualified, this means it's just deducing the std::bitset::reference type that std::bitset's operator[] uses to allow mutations via stuff like mybitset[5] = true;, even though you can't give "true" references to single bits. If reimplemented a second time as a const-qualified operator(), e.g.:

    auto operator()(int x, int y) const {
        assert(0<=x && x<=7);
        assert(0<=y && y<=7);
        return board[8*y x];
    }

you could use auto again for consistency, though it doesn't save any complexity (the return type would be bool in that case, matching std::bitset's const-qualified operator[], no harder to type than auto).

The choice to use operator() is an old hack for multidimensional data structures to work around operator[] only accepting one argument; rather than defining operator[] to return a proxy type (which itself implements another operator[] to enable access to the second dimension), you define operator() to take an arbitrary number of arguments and efficiently perform the complete lookup with no proxies required.

CodePudding user response:

operator() is the name of the function, which is then followed by another pair of parentheses listing the arguments. It is the function-call operator and overloading it allows you to make objects that act like functions/function pointers. In this case, it allows:

BitBoard thing;
thing(i, j); // looks like a function!

In this particular case, it's being used for indexing (like a[i]) but the subscript operator operator[] doesn't allow multiple indexes and the function-call operator does. So it was pretty common to see this for multi-dimensional arrays.

However, the new "preferred" style for multiple indexes in C is to pass a list to the subscript operator:

BitBoard thing;
std::cout << thing[{i, j}];

This would be accomplished by operator[](std::array<int, 2> xy).

But the author of this class has chosen the old way, that looks like a function call.

Overloaded operator() is also what makes lambda expressions tick inside.

  • Related