有没有办法在没有参数的情况下在其函数中获取数组结构的索引?
Is there a way to get the index of an array struct in its function without parameters?
正如标题所说,在 Request() 中没有任何附加参数,同时保持它的干净。下面是一个例子:
struct CPerson
{
void Request();
}
void CPerson::Request()
{
// get index
/* EXAMPLES
serverinfo* info;
server.GetInfo(&info, index);
cout << info.username << "\n";
*/
}
CPerson person[64];
int main()
{
for (int i = 0; i < 64; i++)
person[i].Request(); // i = current index
return 0;
}
编辑:固定标题
在这种特定情况下,只要你能保证 CPerson
只存储在这个数组中,你就可以使用 std::distance()
来获取索引,因为 this
发生了成为数组中的有效迭代器。
这与 this - person
实际上是一样的,但是标准库实现可以(而且经常)在调试版本中有额外的安全网,而发布版本没有性能成本。
即使有了额外的安全性,手动错误检查来验证 this
是 person
的一部分的假设仍然是一个好主意。为此,您需要使用 std::less
(与关系运算符相反),因为它保证即使对于不在数组内的指针也是全局有效的。
// C++11 and up.
#include <iterator>
#include <stdexcept>
struct CPerson
{
void Request();
};
CPerson person[64];
void CPerson::Request()
{
// possibly an assert() instead...
if(std::less<CPerson*>{}(this, std::begin(person)) ||
!std::less<CPerson*>{}(this, std::end(person))) {
throw std::out_of_range("not part of person");
}
std::size_t index = std::distance(std::begin(person), this);
}
在 C++20 中,您可以更加通用,这将使 person
成为任何连续的范围,例如 std::vector
:
// C++20 and up.
#include <ranges>
#include <stdexcept>
#include <vector>
struct CPerson
{
std::size_t Index() const;
void Request();
};
CPerson person[64];
// Or possibly
// std::vector<CPerson> person;
std::size_t CPerson::Index() const
{
static_assert(std::ranges::contiguous_range<decltype(person)>);
const CPerson* person_b = std::to_address(std::ranges::begin(person));
const CPerson* person_e = std::to_address(std::ranges::end(person));
if(std::less{}(this, person_b) ||
!std::less{}(this, person_e)) {
throw std::out_of_range("not part of person");
}
return std::distance(person_b, this);
}
void CPerson::Request() {
auto i = Index();
}
正如标题所说,在 Request() 中没有任何附加参数,同时保持它的干净。下面是一个例子:
struct CPerson
{
void Request();
}
void CPerson::Request()
{
// get index
/* EXAMPLES
serverinfo* info;
server.GetInfo(&info, index);
cout << info.username << "\n";
*/
}
CPerson person[64];
int main()
{
for (int i = 0; i < 64; i++)
person[i].Request(); // i = current index
return 0;
}
编辑:固定标题
在这种特定情况下,只要你能保证 CPerson
只存储在这个数组中,你就可以使用 std::distance()
来获取索引,因为 this
发生了成为数组中的有效迭代器。
这与 this - person
实际上是一样的,但是标准库实现可以(而且经常)在调试版本中有额外的安全网,而发布版本没有性能成本。
即使有了额外的安全性,手动错误检查来验证 this
是 person
的一部分的假设仍然是一个好主意。为此,您需要使用 std::less
(与关系运算符相反),因为它保证即使对于不在数组内的指针也是全局有效的。
// C++11 and up.
#include <iterator>
#include <stdexcept>
struct CPerson
{
void Request();
};
CPerson person[64];
void CPerson::Request()
{
// possibly an assert() instead...
if(std::less<CPerson*>{}(this, std::begin(person)) ||
!std::less<CPerson*>{}(this, std::end(person))) {
throw std::out_of_range("not part of person");
}
std::size_t index = std::distance(std::begin(person), this);
}
在 C++20 中,您可以更加通用,这将使 person
成为任何连续的范围,例如 std::vector
:
// C++20 and up.
#include <ranges>
#include <stdexcept>
#include <vector>
struct CPerson
{
std::size_t Index() const;
void Request();
};
CPerson person[64];
// Or possibly
// std::vector<CPerson> person;
std::size_t CPerson::Index() const
{
static_assert(std::ranges::contiguous_range<decltype(person)>);
const CPerson* person_b = std::to_address(std::ranges::begin(person));
const CPerson* person_e = std::to_address(std::ranges::end(person));
if(std::less{}(this, person_b) ||
!std::less{}(this, person_e)) {
throw std::out_of_range("not part of person");
}
return std::distance(person_b, this);
}
void CPerson::Request() {
auto i = Index();
}