Pablo
Pablo

Reputation: 611

Override std::tuple serializing functionality in boost::json

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

Answers (1)

Artyer
Artyer

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

Related Questions