Reputation: 611
boost::json::tag_invoke
works fine with structs, but is totally ignored with std::tuple
.
Look the next example and mind how the two json
arrays are diferent:
Coliru link: https://coliru.stacked-crooked.com/a/e8689f9c523cee2a
#include <iostream>
#include <string>
#include <vector>
#include <boost/json/src.hpp>
using namespace boost::json;
struct Marker
{
double dist{};
double lenght;
int slope{};
};
void tag_invoke( value_from_tag, value& jv, const Marker& marker )
{
jv = { marker.dist, marker.slope };
}
void tag_invoke( value_from_tag, value& jv, const std::tuple<double, double, int>& marker )
{
jv = { std::get<0>(marker), std::get<2>(marker) };
}
int main()
{
boost::json::object json;
std::vector<Marker> markers1{ {0.0, 100.0, 8}, {250.0, 75.0, -6}, {625.0, 200.0, 11}, {830.0, 55.0, -3} };
std::vector<std::tuple<double, double, int>> markers2{ {0.0, 100.0, 8}, {250.0, 75.0, -6}, {625.0, 200.0, 11}, {830.0, 55.0, -3} };
json["grad1"] = boost::json::value_from(markers1);
json["grad2"] = boost::json::value_from(markers2);
std::cout << boost::json::serialize(json) << std::endl;
}
Is there any way to overwrite the std::tuple
to boost::json::value
to only extract the first and third members?
Upvotes: 1
Views: 250
Reputation: 40881
These functions are found via ADL. With std::tuple<double, double, int>
, only overloads in the std::
namespace are searched, which your overload is not in, so it isn't found.
Boost suggests to either put it where ADL can find it, or in the boost::
namespace if not possible.
So you can put it in the boost namespace:
namespace boost {
void tag_invoke( value_from_tag, value& jv, const std::tuple<double, double, int>& marker )
{
jv = { std::get<0>(marker), std::get<2>(marker) };
}
}
Or you can associate it with the ::
namespace:
struct MyTuple : std::tuple<double, double, int> {
using tuple::tuple;
};
void tag_invoke( value_from_tag, value& jv, const MyTuple& marker )
{
jv = { std::get<0>(marker), std::get<2>(marker) };
}
// ...
std::vector<MyTuple> markers2{ ... };
Upvotes: 1