pfr
pfr copied to clipboard
Member pointers functionality
Hello Anton. I have some idea and i want to suggest it for you. This patch will add pretty useful functionality for extracting member pointer of some structure. For example:
struct Foo
{
char ch;
short id;
short opt;
int value;
};
auto ch_memptr = boost::pfr::get_memptr<0>(Foo{});
auto id_memptr = boost::pfr::get_memptr<1>(Foo{});
auto opt_memptr = boost::pfr::get_memptr<2>(Foo{});
auto value_memptr = boost::pfr::get_memptr<3>(Foo{});
auto obj = Foo{};
obj.*ch_memptr = 'c';
obj.*id_memptr = 100;
obj.*opt_memptr = 200;
obj.*value_memptr = 3000;
std::cout << obj.ch << " " << obj.id << " " << obj.opt << " " << obj.value << std::endl; ///< will print "c 100 200 3000"
Its just a draft - not a final code. If you are interested - i will continue for it.
This may help to resolve this issue:
https://github.com/boostorg/pfr/issues/62
BUT i unfortunately do not know how to make get_memptr constexpr((
Good idea!
I''ve simplified it a little bit https://godbolt.org/z/e8rKWrrEs
In my implementation problems are the same:
- pointer arithmetic is not a constant expression (bit_cast refuses to convert pointers to integers)
- Something must be done with the default constructor
Something must be done with the default constructor
template<typename T> struct declval_helper { static T value; };But it not for clang and msvc https://godbolt.org/z/nYz6M61YT- What if we pass a NULL reference into boost::pfr::get? This is works good, but i cant anticipate the consequences
Something must be done with the default constructor
- Why don't we use the already checked
offset_based_getter? In my opinion it solves this problem good. https://godbolt.org/z/hfxbnvqrE This works on MSVC too
I tried to construct constexpr member pointer getter:
GCC and msvc are promising: https://godbolt.org/z/hPa9718aY https://godbolt.org/z/Th8KTKxns
Caveats:
- msvc static assert: same member pointer at runtime, but not recognized as equal at compile time.
- only for not final classes
- clang not works with this technique
@schaumb interesting. Unfortunatelly, refl cannot be passed as template parameter, only orig can.
@denzor200
I created a gcc ticket, because it is a compiler bug (probably?).
msvc constexpr member pointers can be used as template parameter. But:
template<auto> struct X {};
static_assert(std::is_same_v<X<refl>, X<orig>>); // ERROR
template <auto V> decltype(V) wash() { return V; };
static_assert(&wash<refl> == &wash<orig>); // OK
static_assert(wash<refl>() == wash<orig>()); // OK
// compiler save first call function instance template argument (currently the refl), so:
static_assert(wash<refl>() == refl); // OK
static_assert(wash<orig>() == orig); // ERROR
Not equality problem occures only if the original member pointer is used. But wash can be used as equality checker.
@schaumb I created clang ticket here: https://github.com/llvm/llvm-project/issues/56541
Let's see where the answer will be faster :)