自动类型推导并将lambda传递给std :: function参数

时间:2017-01-20 12:45:28

标签: c++ c++11 lambda

让我们假设我有一个具有以下签名的函数:

void foo(std::function<void(int&)>& bar);

以下调用成功编译:

foo([](int& x) { ++x; });

这也成功编译:

std::function<void(int&)> myFunction = [](int& x) { ++x; };
foo(myFunction);

但是使用自动类型推导它突然无法编译:

auto myFunction = [](int& x) { ++x; };
foo(myFunction);

AFAIK推断出的lambda类型是未指定的,但它应该作为一个函子/可调用。我不明白的是,如果不允许将同一个lambda作为同一类型的函数参数传递,怎么可能将同一个lambda分配给std::function<void(int&)>

使用-std=c++11在GCC v4.8.5上进行测试。

3 个答案:

答案 0 :(得分:5)

考虑到这种情况;

std::function<void(int&)> myFunction = [](int& x) { ++x; };
foo(myFunction);

转换发生,结果存储在命名对象myFunction中。反过来,命名对象可以绑定到foo所需的引用。

鉴于其他两个案例;

foo([](int& x) { ++x; });
// and
auto myFunction = [](int& x) { ++x; };
foo(myFunction);

可以进行从命名对象myFunction(在第二种情况下)到std::function的转换(在两种情况下);但是暂时产生了。临时无法绑定std::function所需的foo引用,因此错误。如下添加const允许代码编译;

void foo(std::function<void(int&)> const& bar);

允许Temporaries绑定到const个引用。

Sample code

答案 1 :(得分:2)

  

以下调用成功编译:

KnoxContainerManager.getContainers()

错了,does not compile。原因是您无法将临时绑定到引用。

出于同样的原因:

    <receiver
        android:name=".receiver.KnoxContainerReceiver"
        android:exported="true" >
        <intent-filter>
            <action android:name="com.samsung.knox.container.creation.status" />
        </intent-filter>
    </receiver>

public class KnoxContainerReceiver extends BroadcastReceiver{
    @Override public void onReceive(Context context, Intent intent ){
    //do something
    }
}

也不编译。 foo([](int& x) { ++x; }); 的类型是一种lambda,因此临时创建时将其传递给auto myFunction = [](int& x) { ++x; }; foo(myFunction); ,因为myFunction期望foofoo必须被隐式转换到std::function<void(int&)>&

下面:

myFunction

没有临时创建。所以代码编译成功。

答案 2 :(得分:1)

引用与值不同。

OnNavigateFromAsync

这是一个参考。

std::function<void(int&)>&

这是一个值。

std::function<void(int&)>

这是一个参考。

int&

这是一个值。

int

以上作品。

int x = 3.0;

以上不起作用。

int& x = 3.0;

以上作品。

std::function<void(int&)> f = [](int&x){++x;};

以上不起作用。

std::function<void(int&)>& f = [](int&x){++x;};

void foo(std::function<void(int&)>& bar); 会引用foo。这意味着它需要传递一个实际的std::function,而不是可转换为它的东西。

std::function

void foo2(std::function<void(int&)> const& bar); foo2带到const&。在这里,您可以将可转换的内容传递给std::function

std::function

void foo3(std::function<void(int&)> bar); 按值foo3获取。在这里,您可以将可兑换的内容传递给std::function

lambda不是std::function,但只要签名兼容,它就可以转换为lambda。所以这类似于“将std::function传递给double”的情况,其中int转换为double,但您无法获得intint&

C ++允许double临时,但不允许const&,因为&暗示您打算更改它,并且更改不会传播通过临时。