Hi! I'm writing a small JSON parser project at the moment and have hit a slight wall and am unsure how to make it work on my own.
To represent a value within the JSON data, I have a class Value that is a tagged union that looks like
class Value {
private:
ValueType m_type;
union ValueContainer {
int _int;
unsigned int _uint;
bool _bool;
double _double;
String _string;
Object _object;
Array _array;
} m_value;
public:
...
}
where ValueType is an enum of all the types of values supported by JSON, and Object and Array are just type aliases to std::map<String, Value> and std::vector<Value>
Whenever I want to access the stored value, I use a member function on the value like such
json_data["key-to-access"].as<int>()
This has a declaration that looks like
template<typename T> T as() const
and for each of the types supported by the tagged union, I have a definition that looks like
template<> inline int Value::as<int>() const {
if (this->m_type != VALUE_INT)
throw std::runtime_error("Cannot cast as int when value type differs.");
return this->m_value._int;
}
To edit the JSON from the Object that it is stored in after parsing, I also declared a function within the Value class that is almost identical to the first mentioned:
template<typename T> T& as()
Each definition for all the types is identical to their counterpart in the other function declaration.
Everything compiles fine, but when I try and do things like
json_data["key-to-access"].as<int>() = 42;
// or
auto& num_to_change = json_data["key-to-access"].as<int>();
num_to_change = 42;
The value is left unchanged. This is not how I understand lvalue references to work, and I was anticipating this to be an easy addition to what I have so far.
Where may I be going wrong here? If the code provided isn't enough, I can link what I have written so far to github and share it that way.
Thanks to anyone willing to help out.