如何在不在 C/C++ 中声明附加函数的情况下删除重复代码?

How can I de-duplicate code without declaring an additional function in C/C++?

我正在开发国际象棋引擎并致力于移动生成。例如,这是我为黑骑士生成动作的函数:

/** Pseudolegal moves don't take check into account. */
std::vector<uint8_t>
generate_pseudolegal_bknight_moves(std::shared_ptr<Position> position,
                                   uint8_t square) {
  assert(VALID_SQUARE(square));
  assert(position->mailbox[square] == B_KNIGHT);

  uint8_t candidates[8] = {
      NEXT_RANK(PREV_FILE(PREV_FILE(square))),
      NEXT_RANK(NEXT_RANK(PREV_FILE(square))),

      PREV_RANK(PREV_FILE(PREV_FILE(square))),
      PREV_RANK(PREV_RANK(PREV_FILE(square))),

      NEXT_RANK(NEXT_FILE(NEXT_FILE(square))),
      NEXT_RANK(NEXT_RANK(NEXT_FILE(square))),

      PREV_RANK(NEXT_FILE(NEXT_FILE(square))),
      PREV_RANK(PREV_RANK(NEXT_FILE(square))),
  };
  std::vector<uint8_t> moves;

  for (int i = 0; i < 8; i++) {
    uint8_t candidate = candidates[i];
    uint8_t piece = position->mailbox[candidate];
    if (VALID_SQUARE(candidate) && (!IS_BLACK_PIECE(piece))) {
      moves.push_back(candidate);
    }
  }

  return moves;
}

生成白马走法的函数非常相似,只是两个项(宏)发生了变化: B_KNIGHT -> W_KNIGHT,以及 IS_BLACK_PIECE -> IS_WHITE_PIECE

我不希望在本质上为每一块重复移动生成函数,但到目前为止一直这样做,因为它具有最小的运行时开销。 我可以在 args 中包含 bool is_white 或其他内容,并使用三元 is_white ? W_KNIGHT : B_KNIGHT 切换术语,但条件会在运行时增加以前不存在的开销,而且看起来并不那么优雅。我想知道是否有一些编译时功能可以帮助我定义一个函数。

我想我也可以使用内联函数来尝试减少重复代码的数量,但我想知道是否有比这更好的选择。

如果你不想开销,你可以使用模板参数和 if constexpr:

enum class Color { WHITE, BLACK };

template <Color C> std::vector<uint8_t>
generate_pseudolegal_knight_moves(std::shared_ptr<Position> position,
                                  uint8_t square) {
  ...
  if constexpr (C == Color::WHITE) {
    assert(position->mailbox[square] == W_KNIGHT);
  } else {
    assert(position->mailbox[square] == B_KNIGHT);
  }
  ...
}

// Call
auto moves = generate_pseudolegal_knight_moves<Color::WHITE>(...);

标准保证条件将在编译时进行评估,错误的分支将被丢弃。