I built a simple JSON encoder/decoder in C++ (I know there are many excellent solutions for this problem out there; I'm learning the language, and it's simply a challenge to myself, and I'm not about to pretend that my solution is any good).
Initially, I had the following two operator [] overloads:
json& operator[](const std::string& key) {
assert_type_valid(/* "object" type */);
return (*object_data_)[key];
}
json& operator[](size_t index) {
assert_type_valid(/* "array" type */);
return (*array_data_)[index];
}
...
std::unique_ptr<std::unordered_map<std::string, json>> object_data_;
std::unique_ptr<std::vector<json>> array_data_;
And this worked great! I could do something like my_json["someKey"]["someOtherKey"][4]["thirdKey"] to access nested values.
But then, because my project uses a bunch of Windows APIs that make use of both char/std::string and wchar_t/std::wstring, I wanted to make both json and wjson types, so I turned my existing json class and parser into a basic_json<CharType, StringType>.
Now, the same code looks like:
// Using C for CharType and S for StringType for brevity here...
basic_json<C, S>& operator[](const S& key) {
assert_type_valid(/* "object" type */);
return (*object_data_)[key];
}
basic_json<C, S>& operator[](size_t index) {
assert_type_valid(/* "array" type */);
return (*array_data_)[index];
}
...
std::unique_ptr<std::unordered_map<S, basic_json<C, S>>> object_data_;
std::unique_ptr<std::vector<basic_json<C, S>>> array_data_;
Attempting to use either operator [] now results in this error:
error C2666: 'basic_json<char,std::string>::operator []': 2 overloads have similar conversions
could be ...::operator [](size_t)
or ...::operator [](const S &)
or built-in C++ operator[(__int64, const char [8])
I've tried adding a third operator [](const C* key) overload, but that hasn't made a difference.
My actual question: Why has templating caused this?
I'm under the impression that template types are determined at compile time, so presumably the compiler should understand what C and S are and be able to know that I'm not passing in a size_t when I do my_json["someKey"].
Also, I feel like templating has turned the once-pretty code into a huge mess. Is it ever worth simply duplicating a bunch of code in a situation like this? Like having a second parser that just works explicitly with wchar_t and std::wstring?