Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage help #40

Closed
kitts82 opened this issue Nov 25, 2020 · 7 comments
Closed

Usage help #40

kitts82 opened this issue Nov 25, 2020 · 7 comments
Labels
question Further information is requested

Comments

@kitts82
Copy link

kitts82 commented Nov 25, 2020

I just came across this library and I must admit that it's bit too complex for an average user. Nevertheless, i appreciate the immense amount of work into it.
I have a particular requirement that brought me here and i would like to know how to achieve them if that is possible.

  1. Is there an equivalent of offsetof(struct, member) and sizeof(member)? My use case requires me to read and write the whole structure or portions of it as a bytestream. This can be achieved with something like...
    memcpy(buffer, &myStructAsByteStream[offsetof(mystruct, member)], bytesToSend)

2)Is there a way to get the index of a member of the struct?
3) Is there a way to get the member from index? This is the inverse of the previous.

@veselink1
Copy link
Owner

Hello! I agree that the documentation can be improved. Here is how these operations would translate to refl-cpp. If more flexibility is needed, you can always map the compile-time member metadata to whatever runtime structure is useful for your usecase.

// Get member descriptor by index
constexpr refl::trait::get_t<0, refl::member_list<A>> member_first{};
std::cout << "A.members[0]=" << member_first.name.str() << std::endl;

// Get member by name (name must be a constant expression)
constexpr auto x_member = find_one(refl::member_list<A>{}, [](auto m) { return m.name == "x"; });
std::cout << "x_member.name=" << x_member.name.str() << std::endl;

// Get index of member
constexpr auto index_of_x = refl::trait::index_of_v<refl::trait::remove_qualifiers_t<decltype(x_member)>, refl::member_list<A>>;
std::cout << "index_of_x=" << index_of_x << std::endl;

You could cast the member pointer member.pointer to an offset if you need to. If you need more flexibility at runtime, you could use refl::util::map_to_array to convert the field_descriptors to your own custom structure like so:

constexpr auto members = refl::util::map_to_array<MyMemberInfo>(refl::member_list<A>{}, [](auto m) {
    return MyMemberInfo(m); 
});

The following resources might be helpful:

You can also refer to the Introduction.md. Also take a look at the examples at the bottom of that page.

@kitts82
Copy link
Author

kitts82 commented Nov 26, 2020

I have gotten your code to work but still not very clear how i can use it in code especially in non constexpr code. Interestingly, I reached this code when searching for code capable of constexpr compile time operation. Unfortunately, it is a bit too complex for quick comprehension.

I have attached a sample code of what I would like to achieve. It would be much appreciated if you can convert the code to real working code.

#include "refl.hpp"
#include <iostream>
#include <cstdint>

struct Base
{
    uint16_t a = 0;
    uint16_t b = 1;
    uint16_t c = 2;
    uint16_t d = 3;
}

struct DerivedA : public Base
{
    uint16_t e = 4;
    uint16_t f = 5;
    uint16_t g = 6;
}

struct DerivedB : public Base
{
    uint32_t g = 7;
    uint32_t f = 8;
    uint32_t e = 9;
}

void printInfo(Base *obj)
{
    std::cout << "Initial values" << std::endl;
    std::cout << "a = " << refl::value(obj, a) << std::endl;
    std::cout << "e is a member variable at position " << refl::indexof(obj, e) << " with the value " << refl::value(obj, e) << " having an address offset of " << refl::offsetof(obj, e) << std::endl;
}

void main()
{
    DerivedA A;
    DerivedB B;

    printInfo(&A);

    //Set the value of a to 50
    refl::setValue(B, a, 50);

    printInfo(&B);
}


/*Expected output*/
Initial values
a = 0
d is a member variable at position 4 with the value 4 having an address offset of 8;
Initial values
a = 50
d is a member variable at position 6 with the value 9 having an address offset of 16;

@kitts82
Copy link
Author

kitts82 commented Nov 26, 2020

// Get member descriptor by index
constexpr refl::trait::get_t<0, refl::member_list<A>> member_first{};
std::cout << "A.members[0]=" << member_first.name.str() << std::endl;

by using the idex as a template argument for get_t, It is not possible to get the member by a variable index. Is it possible to do something like
refl::reflect<MyStruct>().members[indexVariable].name

@veselink1
Copy link
Owner

No, it is not.
Copied from above: If you need more flexibility at runtime, you could use refl::util::map_to_array to convert the field_descriptors to your own custom structure like so:

constexpr auto members = refl::util::map_to_array<MyMemberInfo>(refl::member_list<A>{}, [](auto m) {
    return MyMemberInfo(m); 
});

Example MyMemberInfo:

struct MyMemberInfo {
    std::string name;

    template <typename Member>
    MyMemberInfo(Member m) 
        : name(m.name.str())
    {
    }
};

Then you would be able to access any property of interest like so members[idx].name at runtime.

@veselink1 veselink1 added the question Further information is requested label Nov 29, 2020
@kitts82
Copy link
Author

kitts82 commented Nov 29, 2020

You could cast the member pointer member.pointer to an offset if you need to.

Could you expand on this? How can a member pointer be converted to offset? Did you mean; cast to size_t and then subtract the value of the pointer to the object that contains the member?

@veselink1
Copy link
Owner

See the possible implementations in the abstract
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0908r0.html

@veselink1
Copy link
Owner

Closing due to inactivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants