Code Monkey home page Code Monkey logo

rttr's People

Contributors

acki-m avatar andreas-schwab avatar andreyg avatar cosmicrey avatar cotsog avatar dand-oss avatar engelmarkus avatar gabyx avatar georgemp avatar gouletr avatar kkzi avatar mrtrizer avatar sbalogh avatar soroshsabz avatar taketwo avatar veawor avatar weatherhead99 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rttr's Issues

Array types: Get value type and create new instance

First, thanks for the great library! I'm looking for a way to retrieve the value type of a type of an array. For example, given auto type = rttr::type::get<std::vector<int>>(), how can I get a type for the array values, i.e. int in this case? Also, how do I create a new instance for the type above and add values to it? type.create() yields an invalid variant.

Unresolved external symbols..

Hi.. first of all looks like an awesome lib but i have some problems linking it..
Whichever lib i link from the 7z archive from the download section of your site i get unresolved external symbols.. i use VisualStudio and trying to link the lib to my 3D engine which is an DLL.. have no idea how to fix it and i don't use cmake so could not follow your last step in "Instal" section

And one question i have is will the registered classes be available to my 3D Editor if i link your lib both to the engine and editor as static library and if not how to change that?

Thanks!

Add alternative class hierarchy registration to avoid RTTR_ENABLE

As RTTR_ENABLE is intrusive to the class it cannot be used with third-party types.

An alternative approach I use is to add a .base_class<T>() member function to the registration interface. This allows a user to manually add base classes to a type when they are not able to - or don't want to - modify a class definition.

namespace thirdparty {
  class Foo : public Bar, boost::thingy {};
}

// later
registration::class_<thirdparty::Foo>("Foo")
  .base_class<thirdparty::Bar>()
  .base_class<boost::thingy>
  .constructor<>();

Trying to register method which returns std::unique_ptr

Hello,

I have a class which has a method that returns a std::unique_ptr. It basically constructs an object and gives ownership back to the caller using the std::unique_ptr to transfer ownership.

It uses std::move inside when returning.

The problem is while trying to register this method I get the error:

Error C2338 The given value is not copy constructible, try to add a copy constructor to the class. rttr\detail\variant\variant_impl.h 56

Maybe a new method policy for this might work?

RTTR and STL/STL-like types/objects

So since i was working with RTTR porting from the old library i came across another issue: STL/STL-like types and serialization of those, my projects uses types reflected in the old library such as std::string and others and my internal STL types such Map, Set, HashMap, and a bit of the EASTL and other templated classes/structs, all of those fields are serialized into JSON/Binary files at the end.

i saw in the issue #30, you're still working an solution for somewhat my problem with the variant_map_view approach, there's some kind of workaround, without relying with proxy classes, your already implemented wrapper_mapper may work for templates which has only one parameter...

Thanks you.

Add 'constexpr' eveywhere where reasonable

Due the lack of support for constexpr specifier in VS 2013, many functions are not declared with constexpr. Please add it everywhere where reasonable. Use therefore RTTR_CONSTEXPR.

Polymorphic assignment of raw pointer properties does not work

I guess this is more a bug + feature request rolled into one.

First, the RTTR equivalent of the following regular C++ code does not work (don't have a working sample right now, but I think you get it):

class Base
{
};

class Derived : public Base
{
};

class Foo
{
	Base* mBase;
};

Derived* derived = new Derived();
Foo foo;
foo.mBase = derived; // Assigning pointer-to-derived to pointer-to-base. Works in regular C++, fails in RTTR.

So, we're new'ing a Derived, then assigning that to a pointer-to-base through RTTR.

In addition, the following situation does not work in either C++ or RTTR, but can work in RTTR and is extremely useful for things like object deserialization, so consider this a feature request:

class Base
{
};

class Derived : public Base
{
};

class Foo
{
	Derived* mDerived;
};

Base* base= new Derived();
Foo foo;
foo.mDerived = base; // Assigning pointer-to-base to pointer-to-derived. Fails in both C++ and RTTR.

So, we're new'ing a Derived, then assigning that to a pointer-to-base, then trying to assign that to a pointer-to-derived. In C++ this is illegal, because the compiler can't know that Base* is actually a valid Derived* instance (so it requires an explicit cast), but in RTTR we can know that this is a valid assignment, since we know the actual type of the instance.


The first bug (not being able to assign pointer-to-derived to pointer-to-base) is caused by the fact that ptr_type<T> argument::is_type() returns false when faced with this situation. That, in turn, is caused by the implementation to be wrong:

template<typename T>
RTTR_INLINE argument::ptr_type<T> argument::is_type() const RTTR_NOEXCEPT
{
    return ((rttr::type::get<T>() == m_type) ||
             m_type == type::get<std::nullptr_t>() ||
             (m_variant && type::get<variant*>() == type::get<T>()));
}

Specifically it's about the rttr::type::get<T>() == m_type line. This is a specific type match, which in this situation will return false since the type does not actually match exactly. Instead, the code should check if the types match through a is_derived_from check, ie:

template<typename T>
RTTR_INLINE argument::ptr_type<T> argument::is_type() const RTTR_NOEXCEPT
{
    // T is the type of property we're trying to assign *to*, m_type is the type of argument we're trying to assign *from*
    return ((m_type.is_derived_from<T>()) ||
             m_type == type::get<std::nullptr_t>() ||
             (m_variant && type::get<variant*>() == type::get<T>()));
}

This can be further extended to also implement the 'feature request': by not checking m_type directly, but instead using the most-derived-type of the pointer being assigned, we can also assign pointer-to-base to pointer-to-derived:

template<typename T>
RTTR_INLINE argument::ptr_type<T> argument::is_type() const RTTR_NOEXCEPT
{
	// In order to allow assigning a pointer-to-base to a pointer-to-derived (technically illegal in C++, but useful in an RTTI system),
	// we need to retrieve the actual type of the pointer we're assigning.
	type derived_type = m_type;
	if (m_data != nullptr)
	{
		void* ptr = *reinterpret_cast<void**>(const_cast<void *>(m_data));
		if (ptr != nullptr)
			derived_type = type::get_derived_type(ptr, m_type);
	}

	return (derived_type.is_derived_from<T>() ||
		m_type == type::get<std::nullptr_t>() ||
		(m_variant && type::get<variant*>() == type::get<T>()));
}

Now, while I've tested this code and it works for us, I'm less sure about it because I don't know how it behaves in the presence of multiple base classes. In theory it should work fine, but I don't know enough about multiple base classes to say for sure (I barely ever use them).

registration of a unique_ptr

hi i would register a unique_ptr is it possible ?


`#pragma once

#include <rttr/registration>
#include <iostream>
#include <memory>

using namespace rttr;
class MyStruct 
{
public : 
	MyStruct(); 
	void func(double); 
	int data; 
	std::unique_ptr<int> testUniquePointer;

	RTTR_ENABLE()
};


RTTR_REGISTRATION
{
	registration::class_<MyStruct>("MyStruct")
	.constructor<>()
	.property("data", &MyStruct::data)
	.method("func", &MyStruct::func)
	.property("testWeakPointer", &MyStruct::testUniquePointer);
}`

Add support for new property policy: 'as_reference_wrapper'

Add a new property policy called: as_reference_wrapper or similar.
Which should return the property as inside a std::reference_wrapper.
The wrapped type can be retrieve later via type::get_wrapped_type().

This policy is similar to bind_as_ptr, however somebody might prefer a solid wrapper, instead of a raw ptr.

Scripting example

Would be possible to show some rttr usage in scripting language context?
IE: Binding to lua or something else.

Thanks

Increase code coverage to 100%

Increase the code coverage to 100%
Check here what code was not yet covered by the unit tests:
So add more unit test to increase it to full 100%

Vector of pointers as a property

Hi,

Today I was migrating my project to the latest revision of RTTR and came across the following problem. Suppose I have a class that contains a vector of pointers to some object:

struct Container
{
   std::vector<int*> data;
};

With the older version of RTTR I was able to register the vector as a readonly property:

RTTR_REGISTRATION
{
  using namespace rttr;
  registration::class_<Container>("Container")
     .property_readonly("data", &Container::data);
}

However, now compilation fails with this ugly error.

Actually, I have traced down the commit that introduced the problem: 7e651ec, however figuring how to fix it is beyond me :) Any ideas?

Add 'noexcept' eveywhere where reasonable

Due the lack of support for noexcept specifier in VS 2013, many functions are not declared with noexcept. Please add it everywhere where reasonable. Use therefore RTTR_NOEXCEPT.

Comparison of raw pointer properties does not work

When comparing two pointer properties, the wrong result will always be returned. To clarify, assuming some two objects with a raw pointer property:

RTTI::Variant valueA = property.get_value(objectA);
RTTI::Variant valueB = property.get_value(objectB);

bool equal = (valueA == valueB); // Always false

The reason for this is that the following specialization of compare_equal is always selected in the case of raw pointer properties:

template<typename T>
RTTR_INLINE typename std::enable_if<!is_comparable_type<T>::value && !std::is_array<T>::value, bool>::type
compare_equal(const T& lhs, const T& rhs)
{
    return compare_types_equal(&lhs, &rhs, type::get<T>());
}

This is the wrong specialization, because it results in comparing the addresses of two pointers, instead of the values of the pointers.

It should select the following specialization instead:

template<typename T>
RTTR_INLINE typename std::enable_if<is_comparable_type<T>::value && !std::is_array<T>::value, bool>::type
compare_equal(const T& lhs, const T& rhs)
{
    return (lhs == rhs);
}

This is the correct behaviour. The fix is simple: raw pointers should be included in the list of comparable types, that is, is_comparable_type<T> should return true when T = T*.

Can be fixed by simply adding std::is_pointer<T>::value to the definition of is_comparable_type, ie:

template<typename T>
using is_comparable_type = std::integral_constant<bool, std::is_same<T, std::string>::value ||
                                                        std::is_same<T, string_view>::value ||
                                                        std::is_arithmetic<T>::value ||
                                                        std::is_enum<T>::value ||
                                                        std::is_same<T, std::nullptr_t>::value ||
							std::is_pointer<T>::value
                                                 >;

Note: this problem also affects the less-than comparison, but the fix to is_comparable_type also fixes that one.

Clarification / sample app for OSX

So I successfully built an xcode project using
cmake -G Xcode

I can see the rttr dylib target / is this for injecting into existing processes?

My steps so far

I create a new target > Terminal App inside the xcode project
I include the rttr_core framework add the rttr as a dependency and run

include <rttr/registration> // < this line fails.

using namespace rttr;

Normally to resolve this / I'd check to see if the headers are included in the 'framework' - but
it doesn't appear that the rttr is a framwork with public headers / or there's no headers. or I am I missing something.

screen shot 2016-01-25 at 1 03 16 pm

My bigger task is this > https://reverseengineering.stackexchange.com/questions/11840/recycling-private-framework-sdk-no-header-files-osx

I can point to

include "registration_impl.h"

using namespace rttr;
// but this runs into lots of errors.

the registration file appears all commented out

screen shot 2016-01-25 at 1 31 08 pm

Have you considered using virtual box osx simulator?
If anyone gets this working on OSX I'd appreciate any help on steps taken to get up and running.

get_class_method iterates over all methods which is slow

When a user needs to call a method having it's string name, then this would be called:

for (; itr != m_class_method_list.cend(); ++itr)
{
auto& item = *itr;
if (item.m_class_id != raw_type.get_id())
break;

    if (item.m_name_hash != name_hash)
        break;

    if (std::strcmp(item.m_data->get_name(), name) == 0)
        return item.m_data.get();
}

This is slow. Qt does it by generating a switch statement. The overhead could be solved with modern c++1x as well.

Add implicit conversion from a wrapped value inside a variant

Add support for automatic conversion of a wrapped value inside a variant:
Example use case:

int value = 23;
variant var = std::ref(value);
// instead of writing this:
std::cout << var.extract_wrapped_value().to_int() << std::endl;
// user can now write this:
std::cout << var.to_int() << std::endl;

muliple wrapped types

I have used RTTR for a while now and first of all I wanted to renew my gratitude for a great library.

The issue I am facing now concerns template types with multiple template arguments.
For example pairs (e.g. std::pair<std::string, double>) or maps (e.g. std::map<std::string, double>).

Is there a way to implement a "wrapper_mapper" and/or an "array_mapper" to access the wrapped types in these cases?

invoke functions stored in a variant

I know that it is possible to store a function pointer or a lambda in a variant, however a feature that I am missing is the ability to invoke that function dynamically through the variant.

Something like the following:

if (variant.get_type().is_function_pointer()) {
    rttr::method method = variant.to_method();
    method.invoke();
}

Deferred Type Registration (or Register type for later)

Hello!.

I found your reflection library really interesting and worth to try an shot to my projects, replacing an older reflection library called Reflect by HeliumProject, and already started to port my existent frameworks from Reflect to RTTR but i stepped in this issue: Deferred Type Reflection, i mean register an type (such an class or struct) when i enter into a function.

for example in the older Reflect library did something like this:

		template< class ClassT, class BaseT >
		void ComponentRegistrar<ClassT, BaseT>::Register()
		{
			if (...)
			{
				BaseT::s_ComponentRegistrar.Register();
				Reflect::MetaStructRegistrar<ClassT, BaseT>::Register();
			}
		}

When someone calls this class, this will register the base class and after the actual class, BaseT::s_ComponentRegistrar.Register(); consider that function is the same like void ComponentRegistrar<ClassT, void>::Register() which register just the class. i wonder if this would work. The old Reflect library keeps an global hashmap of all registered types.

Other question is about RTTR support class hierarchy of two different class inherits the same class hierarchy for exmaple this tree.

|- BaseClass
   *- DerivedBaseClass : BaseClass
       * DerivedClass : DerivedBaseClass
       * DerivedClass2 : DerivedBaseClass

Add some kind of logging mechanism to RTTR

Due to not using exceptions, some kind of logging mechanism would be very nice to get some kind of message when a code path could not be executed successfully. Especially the registration process, or invoke of properties or methods.

Anyone with some ideas or opinions is welcome to shared it here.

Associative container mapper example

I am experimenting with the new associative_container_view, which I find great. Now trying to "map" non-STL types in order to use them with RTTR, but the documentation is still sketchy.

Since no example is provided, I put together one here for Qt's QHash. I think I got pretty close to the "working" implementation, but it still crashes in some cases. I could use some help in debugging this. If found suitable, I would be glad to see it included in the docs.

Register a class ("mclass") with the custom name ("mymclass") witch contains a raw name ("mclass") causes the type get_name() return a wrong name ("mymymclass")

The patch below solves the problem for me.

diff --git a/src/rttr/detail/type/type_register.cpp b/src/rttr/detail/type/type_register.cpp
index 332fff2..2afc182 100644
--- a/src/rttr/detail/type/type_register.cpp
+++ b/src/rttr/detail/type/type_register.cpp
@@ -440,7 +440,7 @@ void type_register_private::register_custom_name(type& t, string_view custom_nam
     auto tmp_type_list = custom_name_to_id.value_data();
     for (auto& tt : tmp_type_list)
     {
-        if (tt.get_raw_array_type() == t)
+        if (tt.get_raw_array_type() == t && tt != t)
         {
             const auto& orig_name_derived = tt.m_type_data->name;
             custom_name_to_id.erase(orig_name_derived);

type_register.diff.zip

Custom installation directory via CMAKE_INSTALL_PREFIX

RTTR 0.9.5 seems to ignore a given CMAKE_INSTALL_PREFIX command line interface argument:

cmake -G"CodeBlocks - Ninja" -Hrttr-0.9.5-src -Bbuild-rttr-0.9.5/x64/vc140/Release -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl -DCMAKE_INSTALL_PREFIX=../native/rttr/rttr-0.9.5-x64
cmake --build build-rttr-0.9.5/x64/vc140/Release --config Release --target install

cmake -G"CodeBlocks - Ninja" -Hrttr-0.9.5-src -Bbuild-rttr-0.9.5/x64/mgw63/Release -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_INSTALL_PREFIX=../native/rttr/rttr-0.9.5-x64
cmake --build build-rttr-0.9.5/x64/mgw63/Release --config Release --target install

Both installations are made into the directory ${PROJECT_BINARY_DIR}/install, instead of the given directory ../native/rttr/rttr-0.9.5-x64.

Edit: The problem is https://github.com/rttrorg/rttr/blob/master/CMakeLists.txt#L90, where CMAKE_INSTALL_PREFIX is hardcoded. I think it would be better to follow the standard CMake conventions and do not rely on custom variables.

Setting the value of std::shared_ptr-like properties

We have a custom pointer type that we use to do some registration of objects and such. We'd like to expose properties of this type through RTTR. We've got it mostly working, but we're stuck on actually being able to set the values of these properties. We've defined the wrapper_mapper (basically identical to the one for unique_ptr) for our type, so the code looks something like this (simplified):

template<class T>
class ObjectPtr
{
public:
    /** Functions for getting, setting, assigning and such **/
private:
    T* mPtr;
}

namespace rttr
{
	template<typename T>
	struct wrapper_mapper<ObjectPtr<T>>
	{
		using wrapped_type = decltype(std::declval<ObjectPtr<T>>().get());
		using type = ObjectPtr<T>;
		
		inline static wrapped_type get(const type& obj)
		{
			return obj.get();
		}

		inline static type create(const wrapped_type& value)
		{
			return ObjectPtr<T>(value);
		}		
	};
}

Now, given the following type of class, we'd like to be able to get/set the pointer value; it should be as transparent as possible to the user that this is actually a pointer wrapper type. Getting the value works, but settings is problematic:

class Foo
{
private:
    ObjectPtr<Bar> mPointer;
}

Foo* object = new Foo();
Bar* pointee = object->get_type().get_property("mPointer").get_value(object).extract_wrapped_value(); // Works
object->get_type().get_property("mPointer").set_value(object, ObjectPtr<Bar>(new Bar())); // Works
object->get_type().get_property("mPointer").set_value(object, new Bar()); // Doesn't work

So, it almost works, but we can't set the value of this property from a regular pointer (the last case). This is problematic for us, because during deserialization we want to set the values of these pointers (i.e. pointer fixup, like we do with regular pointers), but we only have naked pointers, so set_value fails. From our previous discussion in #56, I know that RTTR expects the value type to match exactly, and that we can use variant::convert to do this:

variant var = b;
auto ret = var.convert(prop.get_type()); // will convert internaly 'Base*' to 'Derived*'

Foo obj;
prop.set_value(obj, var); // will succeed

We're using this code to be able to set raw pointer types in a polymorphic fashion, which is great, but unfortunately the convert code does not deal with this case:

variant var = new Bar();
var.convert(object->get_type().get_property("mPointer").get_value(object).get_type()); // Fails

As an additional curiosity, the wrapper_mapper expects a create() function to be defined, which I had hoped would be used for these cases, but as far as I can tell that function is never called and I can't find a place in the codebase where it does. The get function on wrapper_mapper is correctly called as expected when getting the value from this proxy object.

Any ideas on how to approach/solve this problem?

Variant::convert does not function correctly with null pointers if types don't match exactly

Consider the following code:

class Base
{
};

class Derived : public Base
{
};

class SomeOtherClass
{
     Derived* mPointerProperty;
};

SomeOtherClass* object = new SomeOtherClass();
object->mPointerProperty = nullptr;

variant value = object->get_type().get_property("mPointerProperty").get_value(object);

Now, suppose we want to retrieve the pointer value from the variant and store it in a base pointer. We can do two things:

Base* pointer_value = value.get_value<Base*>(); // Works because Derived is derived from Base

This works because Derived is derived from Base. Or we can do:

bool converted_ok = false;
Base* pointer_value = value.convert<Base*>(&converted_ok);

This doesn't work; garbage is returned and converted_ok remains false, which is unexpected. The reason for this appears to be that variant::convert does not correctly deal with inheritance hierarchies when the value is a nullptr; when faced with this case, it goes through variant::try_pointer_conversion, which calls type::apply_offset, which returns a nullptr (because ptr is null), causing the function to fail.

I'm not sure how to fix it this time :)

Build in VS2017 failing

I'm trying to build this excellent library in the freshly released VS2017, but so far had no luck with that.

Something in type_register.cpp seems off.

Just in case, although it should be reproducable, here's a log

Raw pointer properties don't seem to work

I'm trying to register a class with raw pointer properties (i.e. no smart pointer stuff) and RTTR (0.9.5) does not seem to handle it correctly. The issue seems to be that pointers are being assigned by value. This manifests itself in two different ways:

  1. Setting a value on a pointer property whose current value is null will sometimes crash, but when it doesn't crash won't assign anything at all.
  2. A pointer property of a type whose assignment operator is inaccessible will not compile at all.

Both are pretty unexpected, but looking at the code this seems to be by design, which seems pretty odd. I'm building on Windows using VS2015, for x64 bit.

Minimal repro case:

struct Pointee
{
public:
	// If you uncomment this line the code will no longer compile. If you leave it commented, the code will compile but crash
	//Pointee& operator=(const Pointee&) = delete;
};

struct ClassWithPointer
{
public:
	Pointee* mPointee = nullptr;	
};


RTTR_REGISTRATION
{
	using namespace rttr;

	registration::class_<Pointee>("Pointee")
					.constructor<>();

	registration::class_<ClassWithPointer>("ClassWithPointer")
					.constructor<>()(policy::ctor::as_raw_ptr)
					.property("mPointee", &ClassWithPointer::mPointee);
}


// Main loop
int main(int argc, char *argv[])
{
	rttr::type obj_type = rttr::type::get<ClassWithPointer>();
	ClassWithPointer* obj = obj_type.create().get_value<ClassWithPointer*>();

        // This line will either crash, or if it doesn't crash, the mPointee member will still be null
	obj_type.get_property("mPointee").set_value(*obj, new Pointee());
}

Am I doing something obviously wrong?

variant comparators

I have two enhancement suggestions regarding the variant comparators:

  1. variant::operator>() seems to be missing; while it is perfectly possible to compare the other way around, it would be convenient to have it at one's disposal (along with "<=" and ">=").

  2. I have read in the docs that some types might need the manual registration of the comparators... it would be nice to have the opportunity to check if that happened, so that the program can notice that the result of the comparison is actually invalid: for example by introducing "rttr::type::has_less_than_comparator()" and analogous functions.

Getting the nested type of an array (vector) type?

Consider the following example:

struct DataStruct
{
	float			mFloatProperty = 0.0f;
};

class SomeClass
{
public:
	std::vector<DataStruct>		mArrayOfCompounds;
};

Assuming that DataStruct and SomeClass and their properties are registered in the type system, is there a way to determine/get the nested type of std::vector<DataStruct> property using RTTR? For example, in this example, the nested type of the std::vector<DataStruct> is DataStruct.

I've found the get_rank_type functions in variant_array_view that can do this, but those require an instance of the vector to be able to create the variant_array_view. While I could create an instance of the vector, it seems needlessly expensive to do that just to determine the type of the array. In addition, creating an instance through RTTR also requires the specific vector specialization to be registered with RTTR in order for a constructor to be present, so it's quite inconvenient.

Is there a better way to determine the type?

(Background information: I'm trying to use this to (recursively) collect a list of all types used by a specific type, so I don't actually have an instance lying around)

EDIT: The above example is for arrays/vectors, but the same goes for associative containers, i.e. std::map and friends; I'd like to retrieve their key and value types as well.

Registration of pointer types

Hi, I'm migrating my project from 0.9.0 to the current master and can't figure out what is the "right" way to register a pointer type for a class.

Suppose I have class MyClass. In old times, in the header file I would write:

RTTR_DECLARE_STANDARD_TYPE_VARIANTS(MyClass)

and then in the implementation file:

RTTR_DEFINE_TYPE(MyClass*)
RTTR_REGISTER
{
  rttr::class_<MyClass>();
}

This makes sure that both the class and the pointer-to-class are known by RTTR. With the new version, however, we only need:

RTTR_REGISTRATION
{
  rttr::registration::class_<MyClass>("MyClass");
}

However, this way MyClass* is not visible to RTTR.

I found RTTR_REGISTRATION_STANDARD_TYPE_VARIANTS macro which seems to do what I need, however it's in detail and is not mentioned in the tutorial or docs (at least I did not see it). So I wonder if this is the "official" way to register pointer types. If not, then what should I use?

Thanks.

Linker error when building rttr 0.9.6 with clang on OS X

To generate the ninja files I used: cmake -G "Ninja"
OS X version: 10.11.2
clang version:

$ clang --version
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.2.0
Thread model: posix

Linker error:

[27/55] Linking CXX shared library bin/librttr_core.0.9.6.dylib
FAILED: : && /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++  -frtti -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG -frtti -g -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -dynamiclib -Wl,-headerpad_max_install_names  -o bin/librttr_core.0.9.6.dylib -install_name /Users/mgee/dev/rttr/build/bin/librttr_core.0.9.6.dylib src/rttr/CMakeFiles/rttr_core.dir/constructor.cpp.o src/rttr/CMakeFiles/rttr_core.dir/destructor.cpp.o src/rttr/CMakeFiles/rttr_core.dir/enumeration.cpp.o src/rttr/CMakeFiles/rttr_core.dir/method.cpp.o src/rttr/CMakeFiles/rttr_core.dir/parameter_info.cpp.o src/rttr/CMakeFiles/rttr_core.dir/policy.cpp.o src/rttr/CMakeFiles/rttr_core.dir/property.cpp.o src/rttr/CMakeFiles/rttr_core.dir/registration.cpp.o src/rttr/CMakeFiles/rttr_core.dir/type.cpp.o src/rttr/CMakeFiles/rttr_core.dir/variant.cpp.o src/rttr/CMakeFiles/rttr_core.dir/variant_array_view.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/misc/compare_equal.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/misc/compare_less.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/misc/standard_types.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/conversion/std_conversion_functions.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/constructor/constructor_wrapper_base.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/destructor/destructor_wrapper_base.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/enumeration/enumeration_helper.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/enumeration/enumeration_wrapper_base.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/method/method_wrapper_base.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/parameter_info/parameter_info_wrapper_base.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/property/property_wrapper_base.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/registration/registration_executer.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/type/type_database.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/type/type_register.cpp.o src/rttr/CMakeFiles/rttr_core.dir/detail/variant/variant_compare_less.cpp.o   && :
Undefined symbols for architecture x86_64:
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::data() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::size() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::c_str() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::empty() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::length() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator[](unsigned long)", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

Temporary workaround to get it to link: Remove the reflection of the std::string functions by deleting these lines.

Reasons why variant::create() could fail

I am using rttr as a static library in a Visual Studio 2015 solution.

I have two projects:
Project A: Makes calls to a "deserializer" in Project B. This project generates an executable
Project B: This project depends on rttr_core_lib_s_d.lib. Contains classes to be created dynamically by rttr (variant::create()). Every class is registered to rttr in the corresponding .cpp. This project generates a .lib.

I have this code somewhere in project B, that "dynamically" creates an object of a class declared in project B:
rttr::variant arrayVariant = property.get_value(instance); auto arrayItems = arrayVariant.create_array_view(); rttr::type itemType = arrayItems.get_rank_type(1); // itemType = ProjectB::MyClassType. itemType.is_valid() returns true rttr::variant object = itemType.create(); assert(object.is_valid());

This code is working (object.is_valid() == true) in a specific condition:
If Project A has a reference to Project B and both options "Link Library Dependencies" and "Use Library Dependency Inputs" on that reference are set to "True".

image

However, if I set "Use Library Dependency Inputs" to false, I get "object.is_valid() == false". This only occurs for the creation of objects of classes that are declared in Project B.

For technical reasons relevant to our automated build system, I cannot depend on the flag "Use Library Dependency Inputs" being set to true. Do you have an idea why the creation of objects fails when the option "Link Library Dependencies" is set to false on a project reference?
That option makes the project link against the .obj files instead of the .lib generated.

Thanks!

Multi-metadata

A very useful feature for reflection systems like RTTR is to be able to attach multiple copies of the same metadata key, each with a different value.

A simplified example taken from some production code in a game engine with a reflection system very similar to RTTR:

REFLECT(FooNode)
(
  // used by node graph UI to enumerate the events an instance of FooNode can emit
  node::event<EventA>(),
  node::event<EventB>(),
  node::event<EventC>()
)
.method("something", &type::something)
.property("thing", &type::thing);

Notably that interface doesn't even require an explicitly-named metadata key and instead just keys metadata by the type of the metadata itself. However, an interface that still requires the user to specify keys but allowed multiple values would be good on its own. Key-less metadata is not explicitly required, though it can be a further convenience (perhaps by just using the type of the value as the key if no key is explicitly specified?).

Remove branching when calling a wrapper method

All wrappers (property, method, constructor, destructor & enumeration) currently hold a pointer to the wrapper base class.
When the client holds a valid item, the pointer is set, otherwise its a nullptr.
Every invoke of a member method for the wrappers mentioned above, checks for nullptr.
That's an unnecessary check, just provide for the invalid case a derived class,
which handles this case. All if checks could be removed.

To get the idea:

Current implementation:

variant method::invoke(instance object) const
{
    if (is_valid())
        return m_wrapper->invoke(object);
    else
        return variant();
}

New implementation:

variant method::invoke(instance object) const
{
    return m_wrapper->invoke(object);
}

m_wrapper would point to the a derived class which implement the invalid case.

Assign metadata to a type

Hello,

Is it possible to assign metadata (like we can do for properties) to a type?

I would like to do something like this:

registration::class_("MyClass").metadata(UserFriendlyName, "My Class");

Thanks

enum not converting

I have noticed that conversion of enum's to their raw type with convert() does not work. This surprised me, since it is the same procedure I use for other (non-enum) types. I prepared here a short example test.

Note however, that it is still possible to extract the type with get_value(), so I wanted to ask if this is by design (and why it is so only for enum's).

Add possibility to retrieve used policy from item

It seems to be necessary to retrieve the used binding of registered items at runtime.
Use case was: the policy: bind_as_ptr was used, in order to avoid copying the whole property when retrieving it. In order to avoid copying the whole data, when setting the property back, the user needs to know whether the property has used this kind of policy.

Therefore all items, should expose its used policy via an enum at runtime.

rttr and dlls.

I have a question. If i have some classes with reflection in my app. Then load a .dll with other classes with reflection. Will the ones loaded from a dll be available for me? Or can i somehow introduce their reflection data to my app?

Copy-constructor

I am a new (since yesterday) user of the library, and first of all I wanted to tank you for such an useful tool.

I am starting now to explore the API and running some tests.
It seems that registration of a class requires a copy-constructor, even if rttr::policy::ctor::as_raw_ptr is used.

Small example attached.
test.zip

This fails to build with a static assert.
Am I missing something?

Thank you in advance!

Undefined symbols for architecture x86_64 on MacOS 10.12.3

Hi,
I was trying to compile rttr version 0.95 on MacOS 10.12.3. I followed the instruction from here, and did the following

cd rttc-0.95 
mkdir build; cd build
cmake -DCMAKE_BUILD_TYPE=Release ../
make

It proceeds until 39%:

Scanning dependencies of target rttr_core
[  1%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/constructor.cpp.o
[  2%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/destructor.cpp.o
[  4%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/enumeration.cpp.o
[  5%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/method.cpp.o
[  7%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/parameter_info.cpp.o
[  8%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/policy.cpp.o
[ 10%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/property.cpp.o
[ 11%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/registration.cpp.o
[ 13%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/type.cpp.o
[ 14%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/variant.cpp.o
[ 16%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/variant_array_view.cpp.o
[ 17%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/misc/compare_equal.cpp.o
[ 19%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/misc/compare_less.cpp.o
[ 20%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/misc/standard_types.cpp.o
[ 22%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/conversion/std_conversion_functions.cpp.o
[ 23%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/constructor/constructor_wrapper_base.cpp.o
[ 25%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/destructor/destructor_wrapper_base.cpp.o
[ 26%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/enumeration/enumeration_helper.cpp.o
[ 27%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/enumeration/enumeration_wrapper_base.cpp.o
[ 29%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/method/method_wrapper_base.cpp.o
[ 30%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/parameter_info/parameter_info_wrapper_base.cpp.o
[ 32%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/property/property_wrapper_base.cpp.o
[ 33%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/registration/registration_executer.cpp.o
[ 35%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/type/type_database.cpp.o
[ 36%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/type/type_register.cpp.o
[ 38%] Building CXX object src/rttr/CMakeFiles/rttr_core.dir/detail/variant/variant_compare_less.cpp.o
[ 39%] Linking CXX shared library ../../bin/librttr_core.dylib
Undefined symbols for architecture x86_64:
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::data() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::size() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::c_str() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::empty() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::length() const", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator[](unsigned long)", referenced from:
      __GLOBAL__sub_I_standard_types.cpp in standard_types.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [bin/librttr_core.0.9.5.dylib] Error 1
make[1]: *** [src/rttr/CMakeFiles/rttr_core.dir/all] Error 2
make: *** [all] Error 2

Any idea? Thanks.

P.S. I am using:
cmake version 3.7.1
C compiler AppleClang 8.0.0.8000042
C++ compiler AppleClang 8.0.0.8000042

boost::optional<T> as properties

Hi,

First of all, great library! I have some questions about it.

I have classes with members like this:

class User
{
public:
    boost::optional<string> m_name;
    boost::optional<Mailbox> m_mailbox;
    boost::optional<vector<string>> m_notes;
}

I have declared those members as properties of the class and I can access them correctly.

I have two problems:
1- During the looping over the properties of User, how can I know which one is a boost::optional (without using type name, which is not portable)?
My solution for now is to add metadata manually to each boost::optional property to indicate this, but I have a feeling this might not be the best solution.

2- Before getting the underlying value of the boost::optional property, I need to call is_initialized() on the property(which is of type boost::optional) to make sure the value is valid (otherwise, it's undefined behavior). The problem is that in order to call that method, I need to have an instance of boost::optional which I can't because Type is not known until runtime.
Unless I do a ton of ifs for each type(in this case, one for string, one for Mailbox and one for vector), I don't see how I can call is_initialized() for all types without typing them in the source code like this:

rttr::instance u = User();
for(const auto& property : object.get_properties())
{
    if(!property.get_metadata(IsOptionalKey).to_bool())
        continue;

    const auto& type = property.get_metadata(UnderlyingOptionalTypeKey);
    const rttr::type& underlyingOptionalType = type.get_value<rttr::type>();

    if(underlyingOptionalType == rttr::type::get<string>())
    {
        const boost::optional<string>& val = property.get_value(u).get_value<boost::optional<string>>();
        if(val.is_initialized()) { /* ... */ }
    }
    else if(underlyingOptionalType == rttr::type::get<Mailbox>())
    {
        const boost::optional<Mailbox>& val = property.get_value(u).get_value<boost::optional<Mailbox>>();
        if(val.is_initialized()) { /* ... */ }
    }
}

Is there something I'm missing or there is no easy solution to this?

Add variant_sequential_view class

Similar to the variant_associative_view class, add a new class called variant_sequential_view.
The variant_array_view class should be marked as deprecated.
The advantage of the new class will be:

  • can be easily used in range based for loop
  • less member functions, but same functionality
  • no internal dynamic memory allocation, when iterator is big enough
  • easier internal code to maintain

Public header for variant_associative_view includes a private header

In rttr/src/rttr/detail/variant_associative_view/variant_associative_view_creator_impl.h, variant_associative_view_p.h is included but it is not installed by make install.

To reproduce:

#include <rttr/type>

int main()
{
}

LANG=C g++ test.cpp -I install/include -L install/lib -l rttr_core

In file included from install/include/rttr/detail/variant_associative_view/variant_associative_view_creator.h:63:0,
                 from install/include/rttr/detail/variant/variant_data_policy.h:35,
                 from install/include/rttr/detail/variant/variant_impl.h:36,
                 from install/include/rttr/variant.h:950,
                 from install/include/rttr/detail/type/get_create_variant_func.h:32,
                 from install/include/rttr/detail/type/type_impl.h:36,
                 from install/include/rttr/type.h:1080,
                 from install/include/rttr/type:31,
                 from test.cpp:1:
install/include/rttr/detail/variant_associative_view/variant_associative_view_creator_impl.h:31:77: fatal error: rttr/detail/variant_associative_view/variant_associative_view_p.h: No such file or directory
 #include "rttr/detail/variant_associative_view/variant_associative_view_p.h"

Return ranges instead of vectors

RTTR functions like get_properties currently return a std::vector object. Creation of this object requires allocating backing memory every single time that get_properties is invoked.

A superior approach would be to return a "range" type like an array_view instead of the vector in such interfaces. This type would still allow using C++ iteration and range-based-for over the returned elements, but would remove the use of allocation.

An array_view may be too simple to use for some of the data structures used in RTTR's internals, of course, but an iterator_range can also be written that operates on a custom iterator type that is able to properly introspect RTTR's data.

Using such range types judiciously removes all need to ever allocate temporary containers while querying or enumerating the type database with very little (if any) loss of features currently present in RTTR.

// range for array-like containers
template <class T>
struct array_view {
  T* _begin = nullptr;
  T* _end = nullptr;

  array_view() = default;
  array_view(T* being, T* end) : _begin(begin), _end(end) {}

  T* begin() const { return _begin; }
  T* end() cont { return _end; }
  size_t size() const { return _end - _begin; }
  T& operator[](size_t i) const { return _begin[i]; }
};

// implementation of a range getter
array_view<property> type::get_properties() const
{
  // rough simulacrum of RTTR internals
  return {m_class_properties.data(), m_class_properties.data() + m_class_properties.size()};
}

// usage of the library doesn't change at all
for (property& p : my_type.get_properties())
  { /*...*/ }

custom registered type name should be used in class templates as well

printing the name of following type:

std::cout << type::get<std::reference_wrapper<std::string>>().get_name() << std::endl;

Results in following output with MSVC 2015:

class std::reference_wrapper<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >

Desired output:

class std::reference_wrapper< std::string >

Every type with which has the original type name included should be replaced with the custom registered name. That are normally templates, but function ptrs should also be honored...

Coding starting point:

type_register.cpp
std::string type_register_private::derive_name(const type_data& wrapper_type, const type_data& array_raw_type, string_view name)

Support for `std::unique_ptr` member properties?

Hi, sorry, it's me again :) I was wondering if RTTR supports std::unique_ptr member properties. From the documentation of wrapper_mapper I conclude that they are supported. However, when I try to register a member field of type std::unique_ptr, I get the following compilation error, which seems to originate in the fact that unique pointers are not copy-constructible. So what is the status actually?

#include <rttr/registration>

struct A
{
  std::unique_ptr<int> p;
};

RTTR_REGISTRATION
{
  using namespace rttr;
  registration::class_<A>("A")
    .property_readonly("p", &A::p);
}

Compiler: GCC 5.4 and Clang 3.8.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.