Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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 person - this, but standard library implementations can (and often do) have additional safety nets in debug builds.

Even with that additional safety, manual error checking is still warranted to validate the assumption. For this, you’ll want to use std::less, as it’s guaranteed to be globally valid even for pointers that are not part of the array.

#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:

#include <ranges>
#include <stdexcept>

struct CPerson
{
    std::size_t Index() const;
    void Request();
};

std::vector<CPerson> person;

std::size_t CPerson::Index() const
{
    static_assert(std::ranges::contiguous_range<decltype(person)>);

    auto person_b = std::to_address(std::ranges::begin(person));
    auto person_e = std::to_address(std::ranges::end(person));

    if(std::less<CPerson*>{}(this, person_b) || 
      !std::less<CPerson*>{}(this, person_e) {
      throw std::out_of_range("not part of person");
    }

    return std::distance(person_b, this); 
}

void CPerson::Request() {
  auto i = Index();
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading