该库使用所谓的嵌入式领域特定语言,它以允许看似不同的语言成为 C++ 程序的另一部分的方式扭曲 C++ 和预处理器语法。
简而言之,魔法。
第一个神奇之处在于:
iod_define_symbol(hello)
这是一个宏,用于生成_hello_t 类型的标识符_hello。
它还创建了一个 _hello_t 类型,该类型继承自名为 iod::symbol<_hello_t> 的 CRTP 帮助程序。
_hello_t 覆盖了各种运算符(包括 operator= 和 operator/),它们的行为与您通常期望的 C++ 对象不同。
GET / _hello = [] () { return D(_message = "Hello world."); }
所以这个调用
operator=(
operator/( GET, _hello ),
/* lambda_goes_here */
);
在 lambda 中类似:
D(_message = "Hello world.");
是
D( operator=(_message, "Hello world.") );
operator/ 和 operator=几乎可以做任何事情。
在 D 的情况下,= 不进行任何分配 - 相反,它构建了一个结构,基本上说“名为 "message" 的字段被分配了值 "Hello world."。
_message 知道它被称为"message",因为它是由宏iod_define_symbol(message) 生成的,他们在其中获取字符串message 并将其存储为_message_t 类型,并创建了变量_message,即该类型的一个实例。
D 采用许多这样的键/值对并将它们捆绑在一起。
lambda 返回这个包。
所以[] () { return D(_message = "Hello world."); } 是一个 lambda,它返回一组键值对附件,以一种奇怪的方式编写。
然后我们在左侧调用operator= 和GET/_hello。
GET 是另一个全局对象,上面重载了operator/。我还没有追踪到它。假设它是iod::get_t 类型(这个名字是我自己编的:再说一次,我没有查过它是什么类型,这并不重要)
然后iod::get_t::operator/(iod::symbol<T> const&) 被重载以生成另一个辅助类型。此类型获取 T 的名称(在本例中为 "hello"),并等待 lambda 分配给它。
当分配给它时,它不会做你期望的事情。相反,它会在 "hello" 和调用该 lambda 之间建立关联,其中该 lambda 应返回一组由 D 生成的键值对。
然后我们将一个或多个这样的关联传递给http_api,它会收集这些捆绑包并构建运行具有这些查询和响应的 Web 服务器所需的数据,可能包括“我将成为 http服务器”。
sl::mhd_json_serve 然后获取该数据和端口号,并实际运行 Web 服务器。
所有这些都是一堆抽象层,使一些反射更容易。生成的结构都具有 C++ 标识符和类似的字符串。类似的字符串暴露在其中,当生成json序列化(或反序列化)代码时,这些字符串用于读取/写入json值。
宏的存在只是为了让编写样板文件更容易。
如果您想了解这里发生的事情,可能有助于进一步阅读的技术包括“表达式模板”、“反射”、“CRTP”、嵌入式“领域特定语言”。
上面的一些内容包含了一些小的“告诉孩子们的谎言”——特别是,运算符语法不像我暗示的那样工作。 (a/b 不等同于operator/(a,b),因为第二个不会调用成员运算符/。理解它们只是函数是我的意图,而不是语法是一样。)
@mattheiuG(该框架的作者)在这篇文章下方的评论中分享了@987654321@,进一步解释了D 和_message 令牌和框架。