加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 无需模板进行优化

发布时间:2020-12-16 07:23:25 所属栏目:百科 来源:网络整理
导读:我正在写一个国际象棋引擎,我有一个看起来像这样的函数: U64 find_moves(Piece type,Team side,uint8_t square,U64 occupied) { switch (type) { case PAWN: { U64 result = 0; result |= occupied bb_normal_moves::pawn_caps[side][square]; if (!(occupi
我正在写一个国际象棋引擎,我有一个看起来像这样的函数:

U64 find_moves(Piece type,Team side,uint8_t square,U64 occupied) {
    switch (type) {
        case PAWN: {
            U64 result = 0;
            result |= occupied & bb_normal_moves::pawn_caps[side][square];
            if (!(occupied & bb_normal_moves::pawn_moves_x1[side][square])) {
                result |= bb_normal_moves::pawn_moves_x1[side][square];
                if (!(occupied & bb_normal_moves::pawn_moves_x2[side][square])) {
                    result |= bb_normal_moves::pawn_moves_x2[side][square];
                }
            }
            return result;
        }
        case KNIGHT:
            return bb_normal_moves::knight_moves[square];
        case BISHOP:
            return bb_magics::bishop_moves(square,occupied);
        case ROOK:
            return bb_magics::rook_moves(square,occupied);
        case QUEEN:
            return bb_magics::bishop_moves(square,occupied) | bb_magics::rook_moves(square,occupied);
        case KING:
            return bb_normal_moves::king_moves[square];
    }

    return 0; // Can't happen
}

它本质上根据类型参数委托另一个函数调用.在程序周围的许多地方,在循环遍历不同的Piece值之后调用此函数,这恰好是枚举.

不幸的是,这意味着每次在该循环中调用此函数,因此在此函数分支中浪费了大量CPU时间.

我想做的是更改此函数以允许编译器优化调用:

template <Piece type> U64 find_moves(Team side,U64 occupied)

但是我的循环不能编译,因为在编译时无法解析函数调用的目标.

有没有办法优化这个功能,而无需手动展开我的所有循环?

编辑:这是一个调用find_moves的循环的示例:

for (uint8_t piece = 1; piece < 6; piece++) {
    move.info.piece = piece;
    U64 bb_piece = board.bb_pieces[team][piece];

    while (bb_piece) {
        uint8_t from = pop_bit(team,bb_piece);
        move.info.from = from;

        U64 bb_targets = find_moves((Piece) piece,team,from,board.bb_all) & mask;

        while (bb_targets) {
            uint8_t to = pop_bit(x_team,bb_targets);
            move.info.to = to;

            buf[buf_size++] = move;
        }
    }
}

解决方法

鉴于Piece枚举的值是1到6,您可以使用模板,std :: make_index_sequence,std :: index_sequence来展开.

对不起,但我只能准备一个最小的例子(没有移动,没有董事会等).

如果你称之为

foo(std::make_index_sequence<6U>{});

在foo()中,您可以使用单个值调用另一个函数(您标记为C 17,因此您可以使用模板折叠)

template <std::size_t ... Ps>
void foo (std::index_sequence<Ps...> const &)
 { (bar<Ps>(),...); }

我的想法是在bar()中你可以放置你的例子的for(uint8_t piece = 1; piece< 6; piece)循环体的内容;我只调用一个简单的(没有其他参数)find_moves()函数.

template <std::size_t Ps>
void bar ()
 { find_moves<pieces(1+Ps)>(); }

现在你可以使用完全特化来开发六个find_moves()模板函数(我只编写std :: cout消息;你使用其他参数,可以将案例的内容放在你的交换机中.

template <pieces P>
void find_moves ();

template <>
void find_moves<Pawn> ()
 { std::cout << "Case Pawn" << std::endl; }

template <>
void find_moves<Knight> ()
 { std::cout << "Case Knight" << std::endl; }

template <>
void find_moves<Bishop> ()
 { std::cout << "Case Bishop" << std::endl; }

template <>
void find_moves<Rook> ()
 { std::cout << "Case Rook" << std::endl; }

template <>
void find_moves<Queen> ()
 { std::cout << "Case Queen" << std::endl; }

template <>
void find_moves<King> ()
 { std::cout << "Case King" << std::endl; }

以下是完整的编译示例

#include <iostream>
#include <utility>
#include <type_traits>

enum pieces { Pawn = 1,Knight,Bishop,Rook,Queen,King };

template <pieces P>
void find_moves ();

template <>
void find_moves<Pawn> ()
 { std::cout << "Case Pawn" << std::endl; }

template <>
void find_moves<Knight> ()
 { std::cout << "Case Knight" << std::endl; }

template <>
void find_moves<Bishop> ()
 { std::cout << "Case Bishop" << std::endl; }

template <>
void find_moves<Rook> ()
 { std::cout << "Case Rook" << std::endl; }

template <>
void find_moves<Queen> ()
 { std::cout << "Case Queen" << std::endl; }

template <>
void find_moves<King> ()
 { std::cout << "Case King" << std::endl; }

template <std::size_t Ps>
void bar ()
 { find_moves<pieces(1+Ps)>(); }

template <std::size_t ... Ps>
void foo (std::index_sequence<Ps...> const &)
 { (bar<Ps>(),...); }

int main ()
 {
   foo(std::make_index_sequence<6U>{});
 }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读