c++ - 如何在不声明C/C++附加功能的情况下对代码进行重复数据删除?

标签 c++ templates chess

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

/** 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;
}
生成白色骑士 Action 的功能非常相似,只改变了两个术语(宏):B_KNIGHT-> W_KNIGHTIS_BLACK_PIECE-> IS_WHITE_PIECE
我不希望本质上为每一个片段都复制移动生成函数,但是到目前为止,因为它具有最小的运行时开销,所以一直都在这样做。
我可以在args中包含bool is_white或其他内容,并使用三元is_white ? W_KNIGHT : B_KNIGHT切换条件,但是条件条件会在运行时增加以前没有的开销,而且看起来并不那么优雅。我想知道是否有一些编译时功能可以帮助我定义一个函数。
我想我也可以使用内联函数来尝试减少重复代码的数量,但是我想知道是否有任何替代方法比这更好。

最佳答案

如果您不想增加开销,可以使用template参数和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>(...);
该标准保证条件将在编译时评估,并且错误分支将被丢弃。

关于c++ - 如何在不声明C/C++附加功能的情况下对代码进行重复数据删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64814789/

相关文章:

c++ - 努力编写 C API 的线程安全 C++ 包装器

wpf - 从模板绑定(bind)到 View 模型的属性

c++ - 在存在不可预测的类型别名的情况下如何处理显式模板实例化?

c - 如何有效地编码/解码压缩的位置描述?

c - 魔术位板移动生成系统最实用的板表示是什么?

hex - 国际象棋棋盘人口

c++ - 如何运行 POCO C++ 服务器页面?

c++ - 如何一起使用 C++ 和 C 可变参数?

c++ - 从类型列表到参数包

c++ - C++ 11使用构造函数声明