veselink1/refl-cpp

Member list empty when using reflect<T>(), but works fine with reflect(const T&)

Closed this issue · 1 comments

Hi @veselink1
First of all, I would like to thank you for developing such an amazing library for C++. It has helped us a lot.
While I was developing functionalities based on refl-cpp, I noticed some very strange behavior and I can't figure out where it comes from.
Below are some code to reproduce the bheavior. I was trying to write an "recursiveForEach" function for nested reflected types. The code below has nothing to do with recursion as I have tried to minimize the code.
Link to goldbolt

Here's the code itself.

#include <iostream>
#include <https://raw.githubusercontent.com/veselink1/refl-cpp/master/include/refl.hpp>

template<typename T, typename Func>
constexpr void forEach(T&& obj, Func&& func)
{

    refl::util::for_each(refl::reflect<T>().members, [&](auto member)
    {
        func(member(obj));
    });
}

template<typename T, typename Func>
constexpr void forEach2(T&& obj, Func&& func)
{

    refl::util::for_each(refl::reflect(obj).members, [&](auto member)
    {

        func(member(obj));
        
    });
}

template<typename T, typename Func>
constexpr void forEachDescriptor(Func&& func)
{

    refl::util::for_each(refl::reflect<T>().members, [&](auto member)
    {
        func(member);
    });
}

struct AAA
{
    int a, b;
};

REFL_AUTO(
    type(AAA),
    field(a),
    field(b)
)

int main()
{
    AAA a{1, 2};

    std::cout << "for each with reflct<T>()" << std::endl;
    forEach( a, [](auto && member)
    {
		std::cout << member << ',';
    });
    std::cout << std::endl;
    
    
    std::cout << "for each with reflct(const &T)" << std::endl;
    forEach2( a, [](auto && member)
    {
		std::cout << member << ',';
    });
    std::cout << std::endl;


    std::cout << "for each discriptor without passing an instance" << std::endl;
    forEachDescriptor<AAA>([](auto member)
    {
		std::cout << get_display_name(member) << ',';
    });
    std::cout << std::endl;
    std::cout << "end of program" << std::endl;
    return 0;
}

I have wrriten 3 wrappers around the for each utility from refl.
The first one takes an instance of the object but uses refl::reflect<T>() to get the descriptor.
The second one takes an instance of the object but uses refl::reflect(const T&) to get the descriptor.
The third one does not take an instance of the object but instead, it iterate through the members using refl::reflect<T>() to get the descriptor.
In theory, the three usage of reflect should hehave exactly the same but the first one will result in empty members. The third one also uses refl::reflect<T>() but different from the first funtion, it works.

When you run this code, you should see the following output

for each with reflct<T>()

for each with reflct(const &T)
1,2,
for each discriptor without passing an instance
a,b,
end of program

I have tried this on gcc 9.4, 10.2, 10.3, all resulted in the same behavior.

I have found the solution.
reference needs to be removed before passing into reflect
std::remove_reference_t solved it.