如何解决c++ boost json ptree中的自定义get方法
我正在尝试访问 boost json ptree 中的缺失值。当key不匹配时,应该调用一个方法,我可以在其中定义返回值。为了计算返回值,我需要访问 ptree。
例子:
ptree 是:
{ "1": 10,"3": 30 }
我想插入返回的值,即
当我查询 "2"
时,我希望返回 20
。
可能吗?
解决方法
在图灵完备的编程语言中一切皆有可能(提示:仅此而已)。
在实际的属性树上,您可以使用 get_optional
,然后使用 value_or_eval
:
Live On Wandbox/Compiler Explorer
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
int main() {
boost::property_tree::ptree pt;
pt.add("1",10);
pt.add("3",30);
for (auto probe : { "1","2","3" }) {
auto lookup = pt.get_optional<double>(probe).value_or_eval([&pt] {
write_json(std::cout << "(interpolate from ",pt);
std::cout << ")\n";
return 42;
});
std::cout << "probe " << probe << " -> " << lookup << "\n";
}
}
打印
probe 1 -> 10
(interpolate from {
"1": "10","3": "30"
}
)
probe 2 -> 42
probe 3 -> 30
问题在于它既不是 JSON 也不是强类型。
替代方案
这是一个随机的例子(字面意思),它使用一个 Json 库而不是属性树:
#include <boost/json.hpp>
#include <boost/json/src.hpp> // header-only
#include <boost/lexical_cast.hpp>
#include <map>
#include <iostream>
#include <iomanip>
#include <random>
using boost::conversion::try_lexical_convert;
namespace json = boost::json;
template <typename Key = double,typename Value = double>
struct MyLookup {
MyLookup(std::string const& text) : data(parse(text))
{ }
using Table = std::map<Key,Value>;
static Table parse(std::string const& text) {
auto raw = json::value_to<std::map<std::string,Value>>(
json::parse(text));
Table converted;
auto key_convert = [](auto &raw_pair) -> std::pair<Key,Value> {
return {boost::lexical_cast<Key>(raw_pair.first),raw_pair.second};
};
std::transform(raw.begin(),raw.end(),inserter(converted,converted.end()),key_convert);
return converted;
}
Value operator[](Key key) const {
auto [low,up] = data.equal_range(key);
if (low == data.end())
throw std::range_error("out of bounds");
if (up == std::next(low)) {
return low->second;
} else {
if (low == data.begin() || up == data.end())
throw std::range_error("out of bounds");
low = std::prev(low);
auto dx = up->first - low->first;
auto dy = up->second - low->second;
auto slope = dy/dx;
return low->second + (key - (low->first)) * slope;
}
}
auto begin() const { return data.begin(); }
auto end() const { return data.end(); }
private:
Table data;
};
int main() {
MyLookup data(R"({ "1": 10,"3": 30 })");
for (auto [k,v] : data) {
std::cout << "table: " << k << " -> " << v << "\n";
}
std::mt19937 prng;
std::uniform_real_distribution<double> probe(0,5);
for (int i = 10; --i;) {
auto key = probe(prng);
std::cout << "Linear interpolation: " << std::setw(7) << key << " -> ";
try {
std::cout << data[key] << '\n';
} catch (std::exception const &e) {
std::cout << e.what() << '\n';
}
}
}
打印例如
table: 1 -> 10
table: 3 -> 30
Linear interpolation: 0.677385 -> out of bounds
Linear interpolation: 4.17504 -> out of bounds
Linear interpolation: 4.84434 -> out of bounds
Linear interpolation: 1.10517 -> 11.0517
Linear interpolation: 1.54084 -> 15.4084
Linear interpolation: 2.7361 -> 27.361
Linear interpolation: 0.94191 -> out of bounds
Linear interpolation: 4.96441 -> out of bounds
Linear interpolation: 4.98231 -> out of bounds
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。