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

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

Open
hanyiabc opened this issue Mar 17, 2023 · 1 comment

Comments

@hanyiabc
Copy link

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.

@hanyiabc hanyiabc changed the title Member list empty when using reflect<T>(), but works fine with reflect(const & T) Member list empty when using reflect<T>(), but works fine with reflect(const T&) Mar 17, 2023
@hanyiabc
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant