传递使用auto-keyword通过非const引用声明的lambda作为std :: function参数类型的参数 [英] Passing lambda declared using auto-keyword by non-const reference as argument to std::function parameter type

查看:214
本文介绍了传递使用auto-keyword通过非const引用声明的lambda作为std :: function参数类型的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

  #include< iostream> 
#include< functional>

//通过值传递函数对象
void foo(std :: function< int(int,int)> f){
std :: cout< f(3,7)<< std :: endl;
}

//通过引用传递const函数对象
void bar(const std :: function< int(int,int)>& f){
std :: cout<< f(3,7)<< std :: endl;
}

//通过引用传递非const函数对象
void fizz(std :: function< int(int,int)>& f){
std :: cout<< f(3,7)<< std :: endl;
}

int main(){

std :: function< int(int,int)> g1 = [](int x,int y){return x * y; };
auto g2 = [](int x,int y){return x * y; };

foo(g1); // OK
foo(g2); // OK
bar(g1); // OK
bar(g2); // OK
fizz(g1); // OK

//编译错误:
//错误:类型为
的引用初始化无效//'std :: function< int(int,int)> &'from
//'main()::< lambda(int,int)>'
//错误:在void fizz function< int(int,int)>&)'
fizz(g2);

}

有人可以向我解释:



(a)为什么 fizz(g2)生成编译错误,其他构造不会?看来我可以通过引用传递一个lambda,如果我明确地在其声明中键入其类型,但不是如果我使用 auto 关键字,或如果我声明函数参数键入 const



(b)函数参数类型中的 const 是什么意思? / p>

(c)在什么情况下我宁愿通过值而不是引用(更新:现在一个单独的问题:C++11:通过引用传递(lambda或其他)函数对象或值?)?



感谢任何洞察。

解决方案>

fizz(g1)案例中, g1 已经是 std: :function 。因此,不需要隐式转换。因此 fizz 的参数是对 g1 的非常量引用。



fizz(g2) g2 不是 c $ c> std :: function 。因此,编译器必须执行隐式转换。



临时对象不能绑定到非const引用; 它们只能绑定到 const 引用或值。因此编译器错误。


函数参数类型中的const是什么意思?


你只能调用 const 对象的成员,你不能隐式地将它转换为非 - const ,并且您无法对其成员执行非 - const 操作。



,就像 const 任何其他用途



一般来说,通过非const引用获取一个参数,它是说一些非常特别的,它打算做什么与该参数。也就是说,你把它作为一个对象,它会做非常量的东西(即:修改该对象)。这就是为什么临时不绑定到非const引用;



除非 fizz 实际上要修改对象,你应该通过值或 const& 传递它。


Consider the following code:

#include <iostream>
#include <functional>

// passing function object by value
void foo(std::function<int(int, int)> f) {
    std::cout << f(3, 7) << std::endl;
}

// passing const function object by reference
void bar(const std::function<int(int, int)> & f) {
    std::cout << f(3, 7) << std::endl;
}

// passing non-const function object by reference
void fizz(std::function<int(int, int)> & f) {
    std::cout << f(3, 7) << std::endl;
}

int main() {

    std::function<int(int, int)> g1 = [] (int x, int y) { return x * y; };
    auto g2 = [] (int x, int y) { return x * y; };

    foo(g1);   // OK
    foo(g2);   // OK
    bar(g1);   // OK
    bar(g2);   // OK
    fizz(g1);  // OK

    // compile error:
    // error: invalid initialization of reference of type
    // 'std::function<int(int, int)>&' from expression of type
    // 'main()::<lambda(int, int)>'
    // error: in passing argument 1 of 'void fizz(std::function<int(int, int)>&)'
    fizz(g2);

}

Would someone explain to me:

(a) Why fizz(g2) generates a compile error, and the other constructs do not? It seems that I can pass a lambda by reference if I explicitly type out its type in its declaration, but not if I use the auto keyword, OR if I declare the function parameter type as const.

(b) What does const in the function parameter type mean here?

(c) In what circumstances would I prefer to pass by value rather than reference (UPDATE: now a separate question: C++11: pass (lambda or other) function object by reference or value?)?

Thanks for any insight.

解决方案

In your fizz(g1) case, g1 is already a std::function. Therefore, there is no need for an implicit conversion. So fizz's parameter is a non-const reference to g1.

In fizz(g2), g2 is not a std::function. Therefore, the compiler must perform an implicit conversion. And the implicit conversion returns a temporary.

Temporary objects cannot be bound to non-const references; they can only bind to const references or values. Hence the compiler error.

What does const in the function parameter type mean here?

You can only call const members of the object, you can not implicitly convert it to non-const, and you cannot perform non-const operations on its members.

You know, just like any other use of const.

Generally speaking, when a function takes a parameter by non-const reference, it is saying something very special about what it intends to do with that parameter. Namely, that you are handing it an object, and it is going to do non-const things with it (ie: modifying that object). That's why temporaries don't bind to non-const references; it's likely to be a mistake by the user, since the temporary may not update the original object you passed.

Unless fizz is actually going to modify the object, you should pass it either by value or by const&.

这篇关于传递使用auto-keyword通过非const引用声明的lambda作为std :: function参数类型的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆