Home > database >  Is there a way to get the index of an array struct in its function without parameters?
Is there a way to get the index of an array struct in its function without parameters?

Time:11-30

As the title says and without any additional parameters in Request() while keeping it clean. Below is an example:

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;
}

edit: fixed title

CodePudding user response:

In this specific case, as long as you can guarantee that CPerson is only ever stored in this array, you can use std::distance() to get the index, since this happens to be a valid iterator into the array.

It's effectively the same thing as just doing this - person, but standard library implementations can (and often do) have additional safety nets in debug builds at no performance cost for release builds.

Even with that additional safety, manual error checking to validate the assumption that this is part of person is still a good idea. For this, you'll want to use std::less (as opposed to the relational operators), as it's guaranteed to be globally valid even for pointers that are not inside the array.

// 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); 
}

In C 20, you can be cleanly more generic about it, which will let person be any contiguous range, like std::vector for example:

// 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();
}
  • Related