Template metaprogramming is one of the things I miss about C++, so I'm using the C preprocessor to accomplish similar results.
I'm trying to move what would be runtime parameters (in this case, color, move_type, and direction) to compile-time.
My problem is, to have the absolute guarantee of compiletime evaluation, I can't do this:
// various definitions for more specific move types, directions
Bitboard get_pawns_able_to(Color color, MoveType move_type, Direction direction, Board *board) {
switch (color) {
case COLOR_WHITE: return get_white_pawns_able_to(move_type, direction, board);
case COLOR_BLACK: return get_black_pawns_able_to(move_type, direction, board);
}
}
I must instead make a lot of these:
Bitboard get_white_pawns_able_to_push_left(const Board *board) {
Bitboard from = board->white;
Bitboard to = board_empty(board);
return from & bitboard_shift_southeast(to);
}
// . . . 63 more similar functions . . .
I often hear that the preprocessor should be avoided unless it does something C cannot do.
I never understood this sentiment, as C is capable of doing everything on its own.
Is this a good use case for the C preprocessor?
I do understand why some people may be averse to the idea:
- No type checking
- Token concatenation is scary
- Less readable, albeit smaller
I would argue this approach, simply due to its less tedious nature, minimizes the number of difficult to spot errors I have the potential to make