简体   繁体   中英

What is this "operator" block of code in c++ class

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];
        }
    }
};

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_at(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() , eg:

    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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM