- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我倾向于只使用我已经在应用程序代码的各个地方使用的映射器模式。但我认为在这种特殊情况下它实际上可能不是最合适的:
任务:
最佳答案
实现目标
我们将编写一个自动翻译器。 假设我们有一个代表我们的有线格式的对象:
JsonObject wire_data;
JsonObject
有一个
add_field
成员函数:
wire_data.add_field("name", "value");
JsonObject
的实际接口(interface)实际上无关紧要,本文的其余部分不依赖于它以任何特定方式实现。
template<class Car>
void add_car_info(JsonObject& object, Car car) {
// Stuff goes here
}
Car
有一个字段,例如Car::getMake()
, 我们的函数 add_car_info
应该自动将该字段添加到 json 对象 Car
没有字段,我们的函数不需要做任何事情。 Car
派生自任何事物,或成为任何事物的基类 struct Car1
{
std::string getMake() { return "Toyota"; }
std::string getModel() { return "Prius"; }
int getYear() { return 2013; }
};
struct Car2
{
std::string getMake() { return "Toyota"; }
int getYear() { return 2017; };
};
struct Car3
{
std::string getModel() { return "Prius"; }
int getYear() { return 2017; }
};
struct Car4
{
long long getSerial() { return 2039809809820390; }
};
JsonObject wire_data;
Car1 car1;
add_field(wire_data, car1);
Car1 car1;
wire_data.add_field("car make", car1.getMake());
wire_data.add_field("car model", car1.getModel());
wire_data.add_field("year", car1.getYear());
Car2 car2;
add_field(wire_data, car2);
Car2 car2;
wire_data.add_field("car make", car2.getMake());
wire_data.add_field("year", car2.getYear());
add_car_info
以一种通用的方式?
C++
没有动态反射,但我们可以使用静态反射来实现(而且效率也会更高)!
template<class Car>
void add_car_info(JsonObject& wire_object, Car car) {
auto translator = getCarTranslator();
// This lambda adds the inputs to wire_object
auto add_field = [&](std::string const& name, auto&& value) {
wire_object.add_field(name, value);
};
// Add the car's fields.
translator.translate(add_field, car);
}
translator
对象只是踢,可以在路上,但是有一个
translator
对象将使书写变得容易
translator
用于汽车以外的东西。
getCarTranslator
开始.对于汽车,我们可能会关心四件事:制造型号、年份和序列号。
auto getCarTranslator() {
return makeTranslator(READ_FIELD("car make", getMake()),
READ_FIELD("car model", getModel()),
READ_FIELD("year", getYear()),
READ_FIELD("serial", getSerial()));
}
// This class is used to tell our overload set we want the name of the field
class read_name_t
{
};
#define READ_FIELD(name, field) \
overload_set( \
[](auto&& obj) -> decltype(obj.field) { return obj.field; }, \
[](read_name_t) -> decltype(auto) { return name; })
template <class Base1, class Base2>
struct OverloadSet
: public Base1
, public Base2
{
OverloadSet(Base1 const& b1, Base2 const& b2) : Base1(b1), Base2(b2) {}
OverloadSet(Base1&& b1, Base2&& b2)
: Base1(std::move(b1)), Base2(std::move(b2))
{
}
using Base1::operator();
using Base2::operator();
};
template <class F1, class F2>
auto overload_set(F1&& func1, F2&& func2)
-> OverloadSet<typename std::decay<F1>::type, typename std::decay<F2>::type>
{
return {std::forward<F1>(func1), std::forward<F2>(func2)};
}
template <class Reader>
class OptionalReader
{
public:
Reader read;
template <class Consumer, class Object>
void maybeConsume(Consumer&& consume, Object&& obj) const
{
// The 0 is used to dispatch it so it considers both overloads
maybeConsume(consume, obj, 0);
}
private:
// This is used to disable maybeConsume if we can't read it
template <class...>
using ignore_t = void;
// This one gets called if we can read the object
template <class Consumer, class Object>
auto maybeConsume(Consumer& consume, Object& obj, int) const
-> ignore_t<decltype(consume(read(read_name_t()), read(obj)))>
{
consume(read(read_name_t()), read(obj));
}
// This one gets called if we can't read it
template <class Consumer, class Object>
auto maybeConsume(Consumer&, Object&, long) const -> void
{
}
};
template <class... OptionalApplier>
class Translator : public OptionalApplier...
{
public:
// Constructors
Translator(OptionalApplier const&... appliers)
: OptionalApplier(appliers)... {}
Translator(OptionalApplier&&... appliers)
: OptionalApplier(appliers)... {}
// translate fuction
template <class Consumer, class Object>
void translate(Consumer&& consume, Object&& o) const
{
// Apply each optional applier in turn
char _[] = {((void)OptionalApplier::maybeConsume(consume, o), '\0')...};
(void)_;
}
};
makeTranslator
现在功能真的很简单。我们只是带了一堆读者,然后用它们来制作
optionalReader
s。
template <class... Reader>
auto makeTranslator(Reader const&... readers)
-> Translator<OptionalReader<Reader>...>
{
return {OptionalReader<Reader>{readers}...};
}
auto getImagesTranslator() {
// Width and height might be implemented as `getWidth` and `getHeight`,
// Or as `getRows` and `getCols`
return makeTranslator(READ_FIELD("width", getWidth()),
READ_FIELD("height", getHeight()),
READ_FIELD("width", getCols()),
READ_FIELD("height", getRows()),
READ_FIELD("location", getLocation()),
READ_FIELD("pixel format", getPixelFormat()),
READ_FIELD("size", size()),
READ_FIELD("aspect ratio", getAspectRatio()),
READ_FIELD("pixel data", getPixelData()),
READ_FIELD("file format", getFileFormat()));
}
关于java - 模式 : Create and translate between data objects and wire formats,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55367816/
我在运行 GNU Visual Debugger 1.2.6 的 XP 虚拟机上尝试打开 Ada 文件 (.adb),但不断出现以下错误: not in executable format: File
我正在尝试获取 io:format/1 的输出结果。 我知道io_lib中也有类似的函数,io_lib:format/2,但是输出不一样。事实上,它根本没有做任何事情。 如果我尝试绑定(bind) i
我在 documentation 中找不到任何内容, 甚至 BreakBeforeBraces: Allman格式化我已经拆分的单行函数 void foo() { bar(); } 我想要类似的东西
请考虑函数f: open Format let rec f i = match i with | x when x () | i -> pp_open_hovbox std_form
如何在列表中的每三个参数后添加一个回车符(使用 ~%)? 例如,我现在: (format nil "~{~a ~}" (list '"one" '"two" '"three" '"four" '"fi
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 6 年前。 Improve
当我尝试在 Ubuntu 上编译 fprintf(stderr,Usage) 时,我遇到了这个错误: error: format not a string literal and no format
运行 cv2.getRectSubPix(img, (5,5), (0,0)) 抛出错误: OpenCV Error: Unsupported format or combination of for
我正在 cocos2d-x-2.1.4 上开发游戏,但是,当我尝试在 Android 上构建它时,它失败并出现错误:格式不是字符串文字且没有格式参数 [-Werror=format-安全] 在文件 C
运行时: $ clang-format -style=Google -dump-config > .clang-format 文件后附有省略号 (...)。 TabWidth: 8 Us
我想在纯函数中将 double 型转换为字符串。我很困惑为什么这不是纯粹的: wstring fromNumber(double n) pure { import std.format;
Common Lisp 的 format 是否有一个特别容易阅读的实现? 我找到了 SBCL's version ,但由于 SBCL 以 性能 Common Lisp 实现而著称,我想知道是否有一个更
嗨,我正在尝试在 JSP 页面上格式化字符串,它给了我错误,正如我在标题中提到的,我的代码是, String header=""; header = 12-29-2011 15;
clang-format 将我的行拆分为 80 列。有没有办法让停止断线? documentation似乎没有解决这个问题。 最佳答案 负责它的配置选项称为 ColumnLimit .您可以通过将其设
我有一个Angular 11项目,试图集成SpreadJS Designer,但在ngcc步骤Compiling @grapecity/spread-sheets-designer-angular :
我正在使用 clang-format 4.0.0来对齐我的个人项目。 我将以下配置用于 clang-format 。 Language: Cpp BreakBeforeBraces: A
我正在使用- char str[200]; ... sprintf(str,"%s", val) msg(str); sprintf(str, "%s: %s",timestr,"\n recv -"
我有这个 double 值: var value = 52.30298270000003 当我将它转换为 string 时,它失去了它的精度: var str = string.Format("{0}
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
如何使用 clang-format 始终将冒号左对齐。我不希望它被禁用:1234,但禁用:1234。 #pragma warning(disable: 1234) 最佳答案 我猜你需要这个。 Spac
我是一名优秀的程序员,十分优秀!