I tried implement something similar to JSON
with pointers as a part of an exam question, and I ended up with an error that I didn't know how to solve.
I had these classes (leaving out the implementation, because I don't think it is important for my error):
struct JSON_BaseObject;
template<typename J_Type>
struct JSON_Value : public JSON_BaseObject;
struct JSON_String : public JSON_Value<std::string>;
struct JSON_Number : public JSON_Value<double>;
struct JSON_Null : public JSON_BaseObject;
using JSON_Children = std::map<std::string, JSON_BaseObject*>;
using JSON_Object = JSON_Value<JSON_Children>;
And I wanted to use the children of type JSON_BaseObject*
in JSON_Object
as a parameter to functions that had different overloads for these derived types, so I made these functions and hoped that they would resolve JSON_BaseObject*
to the respective class (pointer):
void print(JSON_Null*, std::ostream& os);
void print(JSON_String* str, std::ostream& os);
void print(JSON_Number* number, std::ostream& os);
void print(JSON_Object* object, std::ostream& os);
When I ran it, I got a run-time error that the program wasn't able to find the function print(JSON_BaseObject*, std::ostream&)
and I realized that I wasn't as good at c++ as I thought I was.
Is it possible to resolve pointer type parameters from a baseclass like this somehow?
How can I make it nice e.g. begin able to use print(obj, os);
without knowing the derived class of obj
?
After trying out the visitor pattern I realized that it solves all my problems. It also resolves the base pointers in an easy way.
It enabled a nice code like this:
int main()
{
JSON_Object obj = JSON_Object();
JSON_String str = JSON_String("I am a string!");
std::vector<JSON_Base*> basePtrs
{
&obj,
&str
};
Printer printer;
for (auto json : basePtrs)
{
json->PrintMe(printer);
}
}