rttrorg / rttr

C++ Reflection Library
https://www.rttr.org
MIT License
3.17k stars 439 forks source link

unexpected argument mutation #235

Closed yixing-liu closed 5 years ago

yixing-liu commented 5 years ago

I observe some unexpected behavior with argument and variant. They seem more like a bug than a feature.

Here are my code snippets. It compiles with GCC on a Linux box.

#include <iostream>
#include <vector>
#include "rttr/registration.h"
#include "rttr/type.h"

using namespace std;
using namespace rttr;

int sum4(int x1, int x2, int x3, int x4) {
    return (x1+x2+x3+x4);
}

RTTR_REGISTRATION { registration::method("sum4", &sum4); }

int main() {
    vector<argument> args;
    for (int i = 1; i<=4; ++i) {
        variant v = i;
        args.push_back(v);
    } 
    for (auto arg : args) {
        cout << arg.get_value<int>() << endl;
    }
    variant ret = type::invoke("sum4", args);
    if (ret.is_valid()) {
        cout << ret.to_int() << endl;
    }
    for (auto arg: args) {
        cout << arg.get_value<int>() << endl;
    }
}

My expected output is

1
2
3
4
10
1
2
3
4

The actual output is

4
4
4
4
16
16
16
16
16

This seems rather weird to me. Does it have something to do with perfect forwarding or global reference? If I add this line variant tmp = -1; right below variant ret = type::invoke("sum4", args);, then the output will be

4
4
4
4
16
-1
-1
-1
-1

It seems that all values in the vector of arguments args refer to the closest (most recent) value of variant type.

Is this desired behavior?

How can I use invoke if I want to pass in multiple arguments that are only known at runtime? I know type::invoke("sum", {1, 2, 3, 4}) will always work.

chenshaoyu1995 commented 5 years ago

In your code, you expect that argument can store data. However, argument acts like a void * with type information so that all elements in the args point to the same variant v. You can use vector<variant> to store data and convert it to vector<argument> when you need to invoke the function.

yixing-liu commented 5 years ago

Thank you! I will close the issue then.