【问题标题】:How std::function<std::optional<T>()> is compatible with lambda returning T?std::function<std::optional<T>()> 如何与返回 T 的 lambda 兼容?
【发布时间】:2018-07-30 12:33:17
【问题描述】:

我可以创建返回std::optional&lt;Foo&gt;std::function 并分配返回Foo 的lambda。有人可以详细解释一下这是怎么可能的吗?

简单示例:

#include <iostream>
#include <optional>
#include <functional>

int main()
{
    int k = 13;
    std::function<std::optional<int>()> f1;
    f1 = [&] {return k++;}; //implicite int
    std::cout<<"k = " << f1().value() << std::endl;
    f1 = [&] () -> int {return k;}; //explicite int
    std::cout<<"k = " << f1().value() << std::endl;
}

【问题讨论】:

    标签: c++ lambda c++17 std-function


    【解决方案1】:

    constructor of std::optional(重载集中的#8)是有条件的,具体取决于模板参数。在您的情况下(std::optional&lt;int&gt;),您可以隐式构造实例,

    std::optional<int> opt;
    
    opt = 42; /* No problem, implicit construction. */
    

    这正是包装器std::function&lt;std::optional&lt;int&gt;&gt; 所做的。它调用包装函数,该函数返回一个int,并使用这个返回值隐式构造它自己的返回值std::optional&lt;int&gt;

    【讨论】:

    • 我得到了您回答的主要逻辑,但示例具有误导性。这个问题不是关于隐式类型转换,第二个例子下面有解释是错误的。您可以创建std::function&lt;std::optional&lt;A&gt;&gt;,它可以由返回 A 的 lambda 分配。
    • @Logman 一个返回 A 实例的 lambda 可以正常工作,但是一个返回 int 的 lambda 来构造一个 A 就不行了。这是因为std::optional 的条件显式构造函数。这就是我试图在最后一部分中展示的内容。
    • 我真的明白了,但正如我之前所说的,问题不是要展示隐式转换是如何工作的,而是要解释 std::function 是如何工作的。你确实做到了,但你还提供了第二个例子,在这个问题的背景下完全不重要和误导。
    • @Logman 好的,我没有将第二个示例 sn-p 保留在帖子中的议程,因此您认为它具有误导性,因此我将其删除。
    【解决方案2】:

    存在从intstd::optional&lt;int&gt; 的隐式转换。

    std::function 的模板构造函数使用了命名要求Callable,它只要求INVOKE 表达式可以隐式转换为结果类型,而不是它们是同一类型。

    【讨论】:

      【解决方案3】:

      简而言之,分配给std::function的目标必须是std::function的模板参数的参数和返回类型的Callable。

      例如给定:

      • std::function&lt;R(P1, P2)&gt;
      • p1 类型为 P1
      • p2 类型为 P2

      如果f(p1, p2) 格式正确且可隐式转换为R,则可以为其分配目标f。 (*)

      其他答案表明std::optional&lt;int&gt; 可以从int 隐式构造。

      因此,在您的示例中,[&amp;] () -&gt; int {return k;}() 返回一个int,并且可以隐式转换为std::optional&lt;int&gt;

      (*) 请注意,这有点过于简单了,因为严格的定义涉及到调用函数/概念

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-14
        • 2014-06-24
        • 2013-07-04
        • 1970-01-01
        • 1970-01-01
        • 2017-09-01
        相关资源
        最近更新 更多