【问题标题】:C++ function slash operator lambda expressionC++ 函数斜杠运算符 lambda 表达式
【发布时间】:2016-05-25 08:30:47
【问题描述】:

其实我也不知道怎么精确。

今天,我浏览了以下页面:

http://siliconframework.org/docs/hello_world.html

我找到了以下语法:

GET / _hello = [] () { return D(_message = "Hello world."); }

我发现“GET”可以是 lambda 表达式的函数,但我不知道“/”和“_hello”在这里是什么意思,以及它们如何连接到有意义的东西。

另外,“_message =”是什么?

顺便说一句,我的主要 C++ 知识是在 C++11 之前。

我用谷歌搜索了很多。

谁能解释一下?

【问题讨论】:

  • D 在该页面上进行了说明。 / 只是使代码看起来更接近它的样子的库。
  • 这看起来像是一个广泛使用运算符重载的 EDSL。

标签: c++ c++11 lambda c++14


【解决方案1】:

该库使用所谓的嵌入式领域特定语言,它以允许看似不同的语言成为 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(该框架的作者)在这篇文章下方的评论中分享了@98​​7654321@,进一步解释了D_message 令牌和框架。

【讨论】:

  • 加 1 的详细解释,这是有道理的。谢谢。
  • 您可以在这些幻灯片中阅读有关符号以及 D(...) 如何构建对象的更多信息:slideshare.net/MatthieuGarrigues/…。还有一个关于硅框架的简短概述。
  • 只是想告诉你,这是一个很棒的答案,通过阅读我学到了很多东西!
  • @matt 很糟糕,我们没有 operator""<char...> 可以使用引号分隔的字符串。
【解决方案2】:

这不是标准的 C++ 语法,而是特定于框架的。带有下划线前缀的元素(_hello_message 等)与符号定义生成器一起使用,该生成器在编译之前运行并创建必要的定义。

本页末尾有更多信息:http://siliconframework.org/docs/symbols.htmlQt 用它的moc 工具做了类似的事情。

【讨论】:

  • 这个语法有什么不标准
  • @PiotrSkotnicki 您需要使用预编译器来生成带下划线前缀的符号。
  • 但是GET / _hello = [] () { return D(_message = "Hello world."); }本身在C++中是可行的
  • @mcarton 你永远不需要预编译器来生成任何符号(嗯,至少不是这些)。预编译器只能生成编译器随后使用的代码:如果您自己键入该代码,结果将是相同的。
  • 确实,有一个小实用程序可以找到_xxx 符号并为您声明它们。但这绝对是您可以手动完成但写起来并不有趣的事情:github.com/matt-42/silicon/blob/master/silicon/symbols.hh
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-14
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
  • 2015-07-14
相关资源
最近更新 更多