这是什么 "operator" c++ class 中的代码块
What is this "operator" block of code in c++ class
我正在使用某人的 class 作为位图,这是在 64 位位集中存储国际象棋位置的方法。我想知道带有 auto() operator
的部分是做什么的。使用“auto”是因为它 return 是一位,这就是为什么没有为函数指定 return 类型的原因吗?我知道它会检查 x 和 y 是否在棋盘的边界内,如果不在则断言错误。我也明白它 returns 有点对应于位集的 x,y 值对。我也不明白为什么这个函数是这样定义的,加上一对额外的括号。感谢您的帮助!
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];
}
}
};
operator()
是函数的名称,然后是另一对列出参数的括号。它是 function-call 运算符,重载它可以使对象的行为类似于 functions/function 指针。在这种情况下,它允许:
BitBoard thing;
thing(i, j); // looks like a function!
在这种特殊情况下,它被用于索引(如 a[i]
),但下标运算符 operator[]
不允许多个索引,而 function-call 运算符允许。因此,对于 multi-dimensional 数组,这种情况很常见。
但是,C++ 中多个索引的新“首选”样式是将列表传递给下标运算符:
BitBoard thing;
std::cout << thing[{i, j}];
这将由 operator[](std::array<int, 2> xy)
完成。
但是这个 class 的作者选择了老方法,看起来像函数调用。
重载 operator()
也是 使 lambda 表达式在内部打勾的原因。
“额外的”一对括号是因为您正在定义 operator()
,它让 class 的实例表现得像函数。所以如果你有一个:
BitBoard board;
您可以通过以下方式获得 x=3
、y=5
的值:
board(3, 5)
而不是在板上显式调用方法,例如 board.get_bit_at(3, 5)
。
auto
的使用意味着它从std::bitset<64>
的operator[]
推导出return类型;因为该方法不是 const
合格的,这意味着它只是推导出 std::bitset::reference
类型,std::bitset
的 operator[]
用来允许通过 mybitset[5] = true;
之类的东西进行突变,即使您不能为单个位提供“真实”引用。如果第二次重新实现为 const
限定的 operator()
,例如:
auto operator()(int x, int y) const {
assert(0<=x && x<=7);
assert(0<=y && y<=7);
return board[8*y+x];
}
为了保持一致性,您可以再次使用 auto
,尽管它不会节省任何复杂性(在这种情况下,return 类型将是 bool
,匹配 std::bitset
的 const
-qualified operator[]
,并不比 auto
).
更难输入
使用 operator()
的选择是多维数据结构的老招数,可以绕过 operator[]
只接受一个参数;不是将 operator[]
定义为 return 代理类型(它本身实现另一个 operator[]
以启用对第二维的访问),而是将 operator()
定义为采用任意数量的参数并在不需要代理的情况下高效地执行完整的查找。
我正在使用某人的 class 作为位图,这是在 64 位位集中存储国际象棋位置的方法。我想知道带有 auto() operator
的部分是做什么的。使用“auto”是因为它 return 是一位,这就是为什么没有为函数指定 return 类型的原因吗?我知道它会检查 x 和 y 是否在棋盘的边界内,如果不在则断言错误。我也明白它 returns 有点对应于位集的 x,y 值对。我也不明白为什么这个函数是这样定义的,加上一对额外的括号。感谢您的帮助!
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];
}
}
};
operator()
是函数的名称,然后是另一对列出参数的括号。它是 function-call 运算符,重载它可以使对象的行为类似于 functions/function 指针。在这种情况下,它允许:
BitBoard thing;
thing(i, j); // looks like a function!
在这种特殊情况下,它被用于索引(如 a[i]
),但下标运算符 operator[]
不允许多个索引,而 function-call 运算符允许。因此,对于 multi-dimensional 数组,这种情况很常见。
但是,C++ 中多个索引的新“首选”样式是将列表传递给下标运算符:
BitBoard thing;
std::cout << thing[{i, j}];
这将由 operator[](std::array<int, 2> xy)
完成。
但是这个 class 的作者选择了老方法,看起来像函数调用。
重载 operator()
也是 使 lambda 表达式在内部打勾的原因。
“额外的”一对括号是因为您正在定义 operator()
,它让 class 的实例表现得像函数。所以如果你有一个:
BitBoard board;
您可以通过以下方式获得 x=3
、y=5
的值:
board(3, 5)
而不是在板上显式调用方法,例如 board.get_bit_at(3, 5)
。
auto
的使用意味着它从std::bitset<64>
的operator[]
推导出return类型;因为该方法不是 const
合格的,这意味着它只是推导出 std::bitset::reference
类型,std::bitset
的 operator[]
用来允许通过 mybitset[5] = true;
之类的东西进行突变,即使您不能为单个位提供“真实”引用。如果第二次重新实现为 const
限定的 operator()
,例如:
auto operator()(int x, int y) const {
assert(0<=x && x<=7);
assert(0<=y && y<=7);
return board[8*y+x];
}
为了保持一致性,您可以再次使用 auto
,尽管它不会节省任何复杂性(在这种情况下,return 类型将是 bool
,匹配 std::bitset
的 const
-qualified operator[]
,并不比 auto
).
使用 operator()
的选择是多维数据结构的老招数,可以绕过 operator[]
只接受一个参数;不是将 operator[]
定义为 return 代理类型(它本身实现另一个 operator[]
以启用对第二维的访问),而是将 operator()
定义为采用任意数量的参数并在不需要代理的情况下高效地执行完整的查找。