I'm writing an interpretive language using C++. Now the problem is I want to implement features like reassignment:
VAR a = [1,"2",[3,4]]
VAR a[0] = 100
In my language, a List is a vector
of shared_ptr<Data>
, so that you can store different types of data in one list. If someone wants to change an element, I can get the shared_ptr<Data> elem
, and the shared_ptr<Data> value
that's about to be assigned.
Something like:
shared_ptr<Data> elem = visit(elem_node)
shared_ptr<Data> value = visit(value_node)
*elem = *value;
Sorry, I forgot to say that visit() returns a value, not a reference, that's why I didn't just let elem=value;
It turns out the only thing that has been changed is the data member from the Data
class.
But what I want is to let the shared_ptr
"repoint" to a new object. Is it possible?
I've tried dynamic_pointer_cast
, if the origin element and the new value are of the same type, everything is fine. But as I pointed out, I allow different types of elements in one list, so this can only be my last straw.
I've written a demo code based on Remy Lebeau's answer(thanks):
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
struct Data
{
virtual ~Data() = default;
virtual void print() = 0;
};
struct Integer : Data
{
int value;
Integer(int val) : value(val) {}
void print() override { cout << "integer(" << value << ")" << endl; }
};
struct String : Data
{
string value;
String(string val) : value(val) {}
void print() override { cout << "string(\"" << value << "\")" << endl; }
};
struct RuntimeResult
{
RuntimeResult success(const shared_ptr<Data> &value)
{
this->value = value;
return (*this);
}
shared_ptr<Data> registry(const RuntimeResult &res)
{
// this is for handling error
// but this simplify version simply return value;
return res.value;
}
shared_ptr<Data> value;
};
int main()
{
// simulate a List variable
vector<shared_ptr<Data>> list;
list.push_back(make_shared<Integer>(123456));
list.push_back(make_shared<String>("hello"));
RuntimeResult res;
// inside registry, it should be something like visit_IndexNode(elem_node)
// to interprete a node on AST Tree
// but the return is simply like what have shown below
shared_ptr<Data> elem = res.registry(RuntimeResult().success(list.at(0)));
// Using Visual Studio 2019's debugging mode
// we can see that elem's ptr == list[0]'s ptr
// in other word, they are pointing to the same thing(123456)
shared_ptr<Data> value = res.registry(RuntimeResult().success(make_shared<String>("test")));
elem = value;
elem->print(); // "test"
list[0]->print(); // still 123456
return 0;
}
this shows exactly my problem
But what I want is to let the
shared_ptr
"repoint" to a new object. Is it possible?
Yes. Simply assign one shared_ptr<Data>
to another, no casting needed:
shared_ptr<Data> &elem = ...;
shared_ptr<Data> value = ...;
elem = value;