rttr
rttr copied to clipboard
Automatic variant conversion to `std::reference_wrapper`
I really like being able to bind fields of a struct as properties using the as_reference_wrapper
policy. However, it's pretty cumbersome to set property values as I need an explicit std::reference_wrapper
instance. Consider the following example:
struct S {
int v = 0;
};
RTTR_REGISTRATION {
rttr::registration::class_<S>("S")
.constructor()
.property("v", &S::v)(rttr::policy::prop::as_reference_wrapper);
}
void test() {
auto type = rttr::type::get<S>();
auto inst = type.create();
std::cout << type.get_property("v").get_value(inst).to_int() << std::endl;
// 1) Set property via value: doesn't work, ok will be false
auto ok = type.get_property("v").set_value(inst, 2);
// 2) Try to convert value to desired type: doesn't work, ok will be false
auto var = rttr::variant(2);
ok = var.convert(type.get_property("v").get_type());
// 3) Create explicit value and wrapper: this works
auto value = 2;
auto wrapper = std::reference_wrapper<int>(value);
ok = type.get_property("v").set_value(inst, wrapper);
}
It would be nice if variants would be convertible to values to std::reference_wrapper
. Not sure if this is easily possible but it would make registration of structs quite convenient :)
This will not work. The value is copied inside the variant, when you now make a reference inside the variant, the value will be gone and you will hold a dangle reference. Here is the condition, whether you can convert a value to a wrapper class inside a variant: https://github.com/rttrorg/rttr/blob/master/src/rttr/detail/type/type_data.h#L249 E.g. for std::shared_ptr it will work.
Yeah, agree re conversion to a reference_wrapper
. However, if the type in question is copy-constructible it should still be possible to change a property exposed via prop::as_reference_wrapper
via a variant that holds a plain value? Currently, it's difficult to set such a property in a generic way, i.e. if you can't instantiate the actual type that's required manually.
A similar issue arises when working with pointers -- I can't see how I can convert a variant
holding an int*
to int
, for example. What do you think about making it possible to reference and dereference variants, i.e. not via conversion but by creating a new variant? Something like this maybe:
int i = 0;
rttr::variant v = i; // v holding int
auto vref = rttr::variant::ref(v); // vref holding std::reference_wrapper<int>
auto vptr = rttr::variant::addr(v); // vptr holding int*
auto vderef = rttr::variant::deref(vptr) // performs a copy, vderef holding int
This is an interesting approach, i reopen the issue.
using prop::as_reference_wrapper doesn't work for me
class MyClass
{
RTTR_ENABLE()
RTTR_REGISTRATION_FRIEND
private:
std::unique_ptr<uint32_t> mInt32UPtr;
};
RTTR_REGISTRATION
{
rttr::registration::class_<MyClass>("MyClass")
.property("mInt32UPtr", &MyClass::mInt32UPtr) // error MSVC VS2017 15.9.15: \rttr\detail\property\property_accessor.h(45): error C2280: attempting to reference a deleted function
(
rttr::policy::prop::as_reference_wrapper
)
;
}
int i = 0; rttr::variant v = i; // v holding int auto vref = rttr::variant::ref(v); // vref holding std::reference_wrapper
auto vptr = rttr::variant::addr(v); // vptr holding int* auto vderef = rttr::variant::deref(vptr) // performs a copy, vderef holding int
@acki-m are these ref/addr/deref functions implemented already ? or are they planned ?
These methods would help a lot. I'm trying to run a meta function that takes in a reference, but I have a pointer. I've tried cast
but that copies it. I can't think of anything else.