当前位置: 首页 > 知识库问答 >
问题:

lambdas的参数和返回值的类型转换规则是什么?

曾航
2023-03-14

我最近对lambda可以分配给std::functions这一事实感到惊讶。略有不同的意思是当函数指定返回val时,lambda的返回值可能会被忽略,或者参数可能是函数中的引用,但lambda中的值。

请参阅此示例(ideone),其中我突出显示了我怀疑不兼容的内容。我认为返回值不是问题,因为您总是可以调用函数并忽略返回值,但从引用到值的转换对我来说看起来很奇怪:

int main() {
    function<void(const int& i)> f;
    //       ^^^^ ^^^^^    ^
    f = [](int i) -> int { cout<<i<<endl; return i; };
    //     ^^^    ^^^^^^
    f(2);
    return 0;
}

小问题是:为什么这段代码要编译并运行?主要问题是:当与std::function一起使用时,lambda参数和返回值的类型转换的一般规则是什么?

共有3个答案

杜志
2023-03-14
匿名用户

赋值运算符定义为具有以下效果:

function(std::forward<F>(f)).swap(*this);

(14882:2011 20.8.11.2.1第18段)

此引用的构造函数,

template <class F> function(F f);

要求:

F应为可复制的<对于参数类型ArgTypes和返回类型R,code>f应可调用(20.8.11.2)。

其中,可调用的定义如下:

类型为f的可调用对象f对于参数类型ArgTypes和返回类型R,如果表达式INVOKE(f,declval

INVOKE反过来定义为:

>

  • 定义调用(f,t1,t2,…,tN)如下:

    • 。。。这里省略了处理成员函数的案例
    • f(t1,t2,…,tN)在所有其他情况下

    将调用(f,t1,t2,…,tN,R)定义为静态

    由于INVOKE定义变成了一个普通的函数调用,在这种情况下,可以转换参数:如果std::function

    int main() {
        std::function<void(const int& i)> f;
        f = [](int i) -> void { std::cout << i << std::endl; };
        f(2);
        return 0;
    }
    

    返回类型(void)由static\u cast处理

    但是,请注意,在编写本文时,以下内容在使用clang-std=c 1z-stdlib=libc-W转换-Wall编译时会产生错误,但在使用clang-std=c 1z-stdlib=libstdc-W转换-Wall编译时不会产生错误:

    int main() {
        std::function<void(const int& i)> f;
        f = [](int i) -> int { std::cout << i << std::endl; return i;};
        f(2);
        return 0;
    }
    

    这是由于libc实现了C 14中指定的行为,而不是上面描述的修改后的行为(感谢@Jonathan Wakely指出这一点)。@ArunMu在他的帖子中描述了负责同样的事情的libstdc类型特征。在这方面,在处理具有val返回类型的可调用对象时,实现的行为可能会略有不同,具体取决于它们是实现C 11、14还是更新的东西。

  • 公孙向荣
    2023-03-14

    从引用到值的转换在我看来很奇怪

    为什么?

    这看起来也很奇怪吗?

    int foo(int i) { return i; }
    
    void bar(const int& ir) { foo(ir); }
    

    这完全一样。按值取int的函数被另一个按常量引用取int的函数调用。

    bar内部,变量ir被复制,返回值被忽略。这正是std::f

    萧鹏云
    2023-03-14

    可以将lambda分配给std::function类型的函数对象

    也就是说,如果你给你的lambda一个id,这样我们就可以参考它的类型,

    auto l = [](int i) -> int { cout<<i<<endl; return i; };
    

    将其分配给函数

    static_cast<void>(std::declval<decltype(l)&>()(std::declval<const int&>()))
    

    必须格式良好。

    std::declval的结果

    return l(static_cast<int const&>(int{}));
    

    正如您所观察到的,如果函数对象签名具有返回类型val,则返回值将被丢弃;否则,返回类型必须是隐式可转换的。正如Jonathan Wakely指出的,C 11在这方面的行为不令人满意(使用'std::f

     类似资料:
    • 本文向大家介绍js不同数据类型的值的比较,是怎么转换的,有什么规则?相关面试题,主要包含被问及js不同数据类型的值的比较,是怎么转换的,有什么规则?时的应答技巧和注意事项,需要的朋友参考一下 参考回答:

    • 2. 指针类型的参数和返回值 首先看以下程序: 例 23.1. 指针参数和返回值 #include <stdio.h> int *swap(int *px, int *py) { int temp; temp = *px; *px = *py; *py = temp; return px; } int main(void) { int i = 10, j = 20; int *p

    • 我试图创建一个Java方法,它接受一个对象类型和它应该转换成的数据类型。 例如,如果我应该能够返回一个值1作为Int或双根据需要。我使用类传递数据类型作为参数。 问题:如何使方法泛型以接受基于输入参数的返回类型? 下面的代码只是一个示例,它可能在语法上不正确,用于解释我的问题。

    • 我读过这篇文章:java中arrays.aslist(array)与新arraylist (arrays.aslist(ia))之间的差异 当然,包装器上不允许一些列表操作,比如从列表中添加或删除元素,您只能读取或覆盖元素。 如果list2有List接口的引用,我期望它用Java实现List接口中包含的所有方法。https://docs.oracle.com/javase/7/docs/api/j

    • 问题内容: 有了这个代码 我得到以下异常 我的猜测是,由于缺少Jackson,该对象无法转换为JSON。我不明白为什么,因为我以为杰克逊内置弹簧靴。 然后我试图将Jackson添加到pom.xml中,但是我仍然遇到相同的错误 我是否需要更改任何Spring Boot属性才能使其正常工作? 谢谢 问题答案: 问题是Foo中的一个嵌套对象没有任何对象

    • 本文向大家介绍写出js各类型转化为Boolean的值分别是什么?及转化的规则是什么?相关面试题,主要包含被问及写出js各类型转化为Boolean的值分别是什么?及转化的规则是什么?时的应答技巧和注意事项,需要的朋友参考一下 类型 值 Number 除和以外为 String 非空为 Boolean 为 Undefined Null Object 除以外为 Function Symbol BigInt