Reputation: 156
So my goal is to create a function or functor that can return different values. The use case is to convert Json objects into the correct C++ type. For the most part I have this working but I'm running into issues with containers such as std::vector
and std::array
. I know you can't overload a function to just return different value types so I've been using a struct
with template specialization. I figured I would need to use partial template specialization to achieve this but I'm running into compile errors. Here's what my code looks like:
template <typename T>
struct from_json
{
T operator()(const Json::Value &json)
{
return T::fromJson(json);
}
};
template <>
struct from_json<std::string>
{
std::string operator()(const Json::Value &json)
{
return std::string(json.asCString());
}
};
template <typename T>
struct from_json<std::vector<T> >
{
std::vector<T> operator()(const Json::Value &json)
{
std::vector<T> vector;
for (auto obj : json)
vector.push_back(from_json(obj));
return vector;
}
};
Some notes on the code snippet:
I have an abstract class that requires fromJson
to be implemented by my own serializable classes which is what the general case is about. The std::string
generalization seems to work fine. The std::vector
is where things break. The compiler recognizes that that is the specialization that should be used but gives an error when trying to actually use it.
std::vector<std::string> my_vector = from_json<std::vector<std::string> >(json["my_vector"]);
The compiler error is the following:
error: no matching function for call to 'from_json<std::vector<std::__cxx11::basic_string<char> > >::from_json(const Json::Value&)'
std::vector<std::string> my_vector = from_json<std::vector<std::string> >(json["my_vector"]);
note: candidate: constexpr from_json<std::vector<std::__cxx11::basic_string<char> > >::from_json()
It is also worth noting that I am using C++ 11.
I'm definitely open to suggestions on this could be done better if there is a better way.
Thanks!
Upvotes: 1
Views: 584
Reputation: 302757
So in this line:
vector.push_back(from_json(obj));
from_json
in your code is a class template with a defined operator()
. It's not a function or a function object (in that sense, it's kind of like std::hash
). So you can't call it - you need call an instantiation of it.
I'm guessing you mean something like:
vector.push_back(from_json<T>{}(obj));
Or if you're into range-v3:
std::vector<T> operator()(const Json::Value &json)
{
return json | view::transform(from_json<T>{});
}
Upvotes: 2