How to list all member variables of a class / structure in C ++

I am working on some simple reflection for C ++ structures where I want to recursively iterate over all member variables. The code below almost does what I want, but my compiler satisfies: "the recursive type or function of the dependent context is too complex" coming form aggregate_arity<MemberType>::size() , which is based on the implementation of agents_Actents Orients .

Usage example:

 struct B { SPVStruct; var_t<float2_t, true> f4; }; struct A { SPVStruct; var_t<float2_t, true> f2; var_t<float3_t, true> f3; float d; B b; }; A a{}; InitializeStruct<A, true>(a); 

Implementation:

 struct TSPVStructTag {}; #ifndef SPVStruct #define SPVStruct typedef TSPVStructTag SPVStructTag; #endif template< class, class = std::void_t<> > struct has_spv_tag : std::false_type { }; template< class T > struct has_spv_tag<T, std::void_t<typename T::SPVStructTag>> : std::true_type { }; template <class T> void InitVar(T& _Member) {} template <class T, bool Assemble> void InitVar(var_t<T, Assemble>& _Member) { // actual stuff happening here } template <size_t N, class T, bool Assemble> void InitStruct(T& _Struct) { if constexpr(N > 0u) { auto& member = get<N-1>(_Struct); using MemberType = typename std::decay_t<decltype(member)>; if constexpr(has_spv_tag<MemberType>::value) { constexpr size_t n = aggregate_arity<MemberType>::size(); // this is the complex recursion that blows up InitStruct<n, MemberType, Assemble>(member); } else { InitVar(member); InitStruct<N - 1, T, Assemble>(_Struct); } } } template <class T, bool Assemble> void InitializeStruct(T& _Struct) { constexpr size_t N = aggregate_arity<T>::size(); InitStruct<N, T, Assemble>(_Struct); } 

Example

I use has_spv_tag to mark structures that should be mirrored. I can't wait for C ++ 20 with support for actual reflection :(

Thank you for your help!

Edit: I got it to compile and change the iteration order. Now another problem arises: constexpr size_t M = aggregate_arity :: size () returns 0 even for the same type as before it returned the correct value. I checked that the infact type is the same (the first type of structure is a type B) by comparing the hash from typeid. How is it possible for this aggregate to return two different values ​​for the same type?

  template <class T, bool Assemble> constexpr bool is_var_t(var_t<T, Assemble>& _Member) { return true; } template <class T> constexpr bool is_var_t(T& _Member) { return false; } template <class T> void InitVar(T& _Member) { std::cout << typeid(T).name() << std::endl; } template <class T, bool Assemble> void InitVar(var_t<T, Assemble>& _Member) { // actual stuff happening here std::cout << typeid(T).name() << std::endl; } template <size_t n, size_t N, class T> void InitStruct(T& _Struct) { std::cout << "n " << n << " N " << N << std::endl; if constexpr(n < N) { decltype(auto) member = get<n>(_Struct); using MemberType = std::remove_cv_t<decltype(member)>; std::cout << typeid(MemberType).hash_code() << std::endl; if (is_var_t(member)) { InitVar(member); InitStruct<n + 1, N, T>(_Struct); } else { constexpr size_t M = aggregate_arity<MemberType>::size(); InitStruct<0, M, MemberType>(member); } } } 

Edit 2: example for the new version: http://coliru.stacked-crooked.com/a/b25a84454d53d8de

+1
source share
1 answer

Antony Polukhin pointed out the problem: MemberType still had a link to get (_Struct). Code works with

MemberType = std::remove_reference_t<std::remove_cv_t<decltype(member)>>;

 template <size_t n, size_t N, class T> void InitStruct(T& _Struct) { if constexpr(n < N) { decltype(auto) member = get<n>(_Struct); using MemberType = std::remove_reference_t<std::remove_cv_t<decltype(member)>>; if constexpr(has_spv_tag<MemberType>::value) { InitStruct<0, aggregate_arity<MemberType>::size(), MemberType>(member); } else { InitVar(member); } InitStruct<n + 1, N, T>(_Struct); } } 

Now I use has_spv_tag<MemberType>::value to determine which element is the structure I want to list. There was also an error with the order InitStruct<n + 1, N, T>(_Struct);

0
source

Source: https://habr.com/ru/post/1257451/


All Articles