【发布时间】:2019-11-13 07:29:03
【问题描述】:
短: 有许多聪明的库可以让您为各种目的公开一个类的成员,例如序列化、暴露于 lua 环境等。问题是对于每个聪明的解决方案,您必须为每个解决方案注册一个类的东西api,这会导致大量的工作重复和样板。
我可以通过什么方式注册一个类及其成员和方法ONCE 并附加某种标志并获得各种自动生成的方法
长: 假设我有一堂课:
class C {
public:
int i; // Some int
vec3 v; // Some non-POD value
int function(int foo, char bar) // Some function
int hidden; // Some internal stuff I don't want exposed
}
我想做的是能够在声明时标记各种成员和方法,以便将它们自动放入各种样板中:
所以声明可能看起来像:
class C {
public:
LUAREG JSON BINSER int i; // Marks member "i" to be exposed to the lua enviroment,
// JSON serialisable, binary serialisable
JSON vec3 v; // Only exposed to JSON function
LUAREG void someFunction() {} // Marks this method to be exposed to the lua enviroment
}
或者写一个注册函数来完成所有的声明:
void C::register_class() {
registrator::register_class<C>("C")
.addData("i", &i, FLAG_LUA | FLAG_JSON | FLAG_BINARY_SERIALISABLE)
.addFunction("someFunction", &someFunction, FLAG_LUA)
.end_class()
}
(我曾多次看到这种模式——它有名字吗?) 我希望能够为所述类自动生成各种样板函数。例如:
/// Adds all fields with FLAG_JSON to a "json" object to be later serialised
void toJson(const C & c, json & j) {
toJson(c.i, "i", j);
toJson(c.v, "v", j);
}
/// Binary seralises all members with flag FLAG_BINARY_SERIALISABLE and stores the result in s
void serialise(const C & c, string & s) {
serialise(c.i, s);
serialise(c.v, s);
}
/// Registers all stuff with flag FLAG_LUA to some lua environment
void register_lua(lua_State * const L) {
luaReg_FetchContext(L)::addClass("C")
.addData("x", &C::x).comment("Some int") // generates documentation of "int x : Some int"
.addData("v", &C::v).comment("Some vector")
.addFunction("function", &C::function).comment("some function") // generates: "int function(int, char) : some function"
.endClass()
}
/// Register to some *other* lua environment (such as a read only context for rendering)
void register_lua_readonly(lua_State * const L2) {
luaReg_FetchContext(L)::addClass("C")
.addData("x", &C::x, false).comment("Some int")
.endClass()
}
/// Generates some user readable breakdown of all members
string dump() {
...
}
现在你可以看到很多类,手动操作会变得非常乏味、臃肿且容易出错
解决此问题的最佳方法是什么?我很想使用宏来吐出函数,但不知道如何进入注册阶段。干杯!
【问题讨论】:
-
回答您的小问题:使用方法零散构建的类的概念称为builder pattern。将参数链接为方法的 API 样式称为 fluent api
-
集思广益如何完成第一个样式,您可以尝试使用模板来构建特征:
lua_reg<json<binser<T>>>,然后像 Boost PFR 这样的东西来聚合特征以进行注册、序列化等。 -
@parktomatomi 一方面,它不会提供变量的名称
-
@darune 好点,我猜宏是唯一的选择。
标签: c++ boilerplate