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

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

Closed
rovarma opened this issue May 9, 2017 · 6 comments
Closed

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

rovarma opened this issue May 9, 2017 · 6 comments

Comments

@rovarma
Copy link

rovarma commented May 9, 2017

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.

@acki-m
Copy link
Contributor

acki-m commented May 10, 2017

You are absolutely right. That is not possible at the moment.
To view it more generally, we would need a way to retrieve the template parameters from a class template.
That is possible in C# also with the reflection system. However I don't know how to do this in C++.
We would need a type trait to check whether a class is a (or was a) template and then retrieve the list of all parameters.

The big problem here is the distinction between types and non-type template parameters (like int or bool).

template<typename T>
struct is_template : std::false_type
{
};
 
template<template <typename... > class T, typename...Args>
struct is_template<T<Args...>> : std::true_type
{
};

static_assert(is_template<std::string>::value == true, "no class template");  // OK
static_assert(is_template<std::array<int, 2>>::value == true, "no class template");  // FAILS

@rovarma
Copy link
Author

rovarma commented May 15, 2017

Hmm, that seems complicated. I had a go at figuring out a solution, but I didn't manage it.

Perhaps it's possible to start with just an implementation of this for arrays, etc? There's already some custom work done for them through things like array_mapper and I think containers cover 90% of the use-case for nested types.

If you can give me some pointers in the direction of where to start implementing this, I'd be happy to do it.

@acki-m
Copy link
Contributor

acki-m commented May 17, 2017

I have a direction for you now. Maybe you are a preprocessor magician? 😏
Take a look at this code:
http://ideone.com/bKMoS1
We need to add class specializations, for all possible combinations of types and integral value parameters.
Lets say we have a template with 5 parameters and one integral value. We would have to add 2^5 specializations. When we would have three, we need 3^5. And so on...
This is the only solution I come up with.

But can you live with something like this? When we doing a general solution, you would get something like this:

type::get<std::vector<int>>().get_nested_types() => would return 2 types, 'int' & 'allocator<int>'

@rovarma
Copy link
Author

rovarma commented May 22, 2017

I'm not sure I understand your solution. I had a look at the code, but my template-fu is not strong enough :)

What kind of macro magic do you need?

@acki-m
Copy link
Contributor

acki-m commented May 22, 2017

I can elaborate this later in detail. More important is this:
When I will implement it, you would get all template parameters, not only the "important" one.

type::get<std::vector<int>>().get_nested_types() => would return 2 types, 'int' & 'allocator<int>

For an std::string you will get 3 types:

char
std::char_traits<char>
std::allocator<char>

Is this too "good" for you?

@rovarma
Copy link
Author

rovarma commented May 23, 2017

Ah sorry, I missed your question. Yes, that's fine for me. The thing I'm using this for is to be able to calculate a version number for an RTTR type for binary serialization and such, so including all nested types in the version is fine.

@acki-m acki-m closed this as completed in a67f146 May 29, 2017
acki-m added a commit that referenced this issue May 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants