dimanche 22 octobre 2023

C++ how to get the first and the last element in an std::vector by its base memory address

To me, a vector layout looks something like this:

struct MyViewOnHowVectorLooksLike
{
public:
   int* _first, * _last, * _end;
};

Known Parameters:

  1. Address of the std::vector<Type> object
  2. size of the <Type>

Questions:

  1. Find the address of the first element and the last element in the vector

Is there any way to access the first and last elements in a std::vector by its base memory address, which is &Test in the above test case, not by calling any build-in method of the std::vector function eg [0], .front(), etc; (The reason why I'm doing this is to have a static reflection system which could output the content of any given written vector type)

struct FTestData {
    int data;
};

class TestClass {
public:
    // test array
    std::vector<FTestData> testArray;

    TestClass(){}
};

// TEST CASE
FTestData testCon1 = FTestData();
testCon1.data = 111;
FTestData testCon2 = FTestData();
testCon2.data = 222;

TestClass Test = TestClass();
Test.testArray.push_back(testCon1);
Test.testArray.push_back(testCon2);

std::vector<FTestData>* TestData = (std::vector<FTestData>*)((size_t)&Test);
size_t ptr = (size_t)TestData;
FTestData& TestElement1 = (*TestData)[0];
size_t realFirstElementAddress = (size_t)&TestElement1;

// try to get the address of the first element in the vector but it  gives me the wrong address
size_t CustomFirstElementAddress = (*(size_t*)(ptr));

// expecting those two to be the same but it wasnt
assert(realFirstElementAddress == CustomFirstElementAddress);

I thought the _First and _Last are right next to the base address, but it keeps outputting the wrong results.

AddOn: The real problem I am trying to solve is to have a detail panel with my own reflection system, which could allow me do something like this. It works for most common types, and nested class.

{
    if (field.Type == "int") {
        int location[1];
        auto& value = *(int*)((size_t)&Component + Offset + field.Offset);
        memcpy(location, &value, sizeof(location));
        if (ImGui::DragInt(fieldName.c_str(), location, 0.1f, 0.0f, 0.0f, "%.1f"))
        {
            memcpy(&value, location, sizeof(location));
        }
    }
    else if (field.Type == "std::string") {
        char buffer[256];
        memset(buffer, 0, sizeof(buffer));
        auto& value = *(std::string*)((size_t)&Component+ Offset + field.Offset);
        strcpy(buffer, value.c_str());
        if (ImGui::InputText(fieldName.c_str(), buffer, sizeof(buffer))) {
            value = std::string(buffer);
        }
    }
    else if (field.Type == "bool") {
        bool location[1];
        auto& value = *(bool*)((size_t)&Component + Offset + field.Offset);
        memcpy(location, &value, sizeof(location));
        if (ImGui::Checkbox(fieldName.c_str(), location)) {
            memcpy(&value, location, sizeof(location));
        }
    }
    else if (field.Type == "float") {
        float location[1];
        auto& value = *(float*)((size_t)&Component + Offset + field.Offset);
        memcpy(location, &value, sizeof(location));
        if (ImGui::DragFloat(fieldName.c_str(), location, 0.1f, 0.0f, 0.0f, "%.1f"))
        {
            memcpy(&value, location, sizeof(location));
        }
    }
}




Aucun commentaire:

Enregistrer un commentaire