stephenberry/glaze

compile fail when write_beve a vector of std::pair<std::string, std::string>

Closed this issue · 4 comments

std::vector<std::pair<std::string, std::string>>  vv;
std::cout << glz::write_beve(vv).value_or("error") << '\n';  //compile fail

https://gcc.godbolt.org/z/de4hYGMY8

write_json is ok, and return error using read_json
https://gcc.godbolt.org/z/9T6xn76f9

Thanks for reporting this.

By default Glaze treats std::pair as an object with a single key and value: {"key":true}. When Glaze encounters a range of pairs, it writes this out as a concatenated object, which allows for flexible object generation using ranges. However, Glaze does not currently read the same way and therefore breaks round-tripping. There are active issues here #1000 and here #1265 to address this. I really need to get on this.

Here is an example of what this enables:

auto remap_user_port = [](const auto port) { return port + 1024; };
auto user_ports = {std::pair("tcp", std::views::iota(80, 83) | std::views::transform(remap_user_port)),
                            std::pair("udp", std::views::iota(21, 25) | std::views::transform(remap_user_port))};
expect(glz::write_json(user_ports) == glz::sv{R"({"tcp":[1104,1105,1106],"udp":[1045,1046,1047,1048]})"});

The option concatenate can be set to false, which will write out a vector of pairs like [{},{}] rather than concatenating.

std::vector<std::pair<int, int>> v;
expect(!glz::read_json(v, R"([{"1":2},{"3":4}])"));
const auto s = glz::write<glz::opts{.concatenate = false}>(v).value_or("error");
expect(s == R"([{"1":2},{"3":4}])");

This non-concatenating approach will roundtrip.

What is the behavior you are wanting? Are you wanting a concatenated object or separate objects in your array?

If you want an array of arrays, then use std::vector<std::array<std::string, 2>> or use a std::tuple rather than a std::array for mixed type arrays.

BEVE is currently broken and needs to behave like JSON. I'll work on this.

I've added a discussion for how to solve this issue here: #1417

A fix for reading/writing BEVE with vector<pair> has been merged in #1418. Also, vector<pair> now properly roundtrips in JSON and BEVE. Note that the default option is for concatenate = true, but you can set it to false if you don't want your pairs in a vector to be concatenated.