2011-12-12 42 views
8

说我有某种类型包装起来的功能,也许lambda函数:当包含lambda的类型被分配时会发生什么?

template<typename Function> 
    struct my_struct 
{ 
    Function f; 

    my_struct(const Function &f) : f(f) {} 
}; 

当这种类型的实例分配会发生什么?我的理解是lambda是不可变的,并且已经删除了赋值运算符。

然而,当我指定给对象这种类型在下面的代码段中,被发射的没有错误:

// a structure which contains a function; 
// possibly a lambda function 
template<typename Function> 
    struct my_struct 
{ 
    Function f; 

    my_struct(const Function &f) : f(f) {} 

    // XXX adding this assignment operator causes an error 
    //my_struct &operator=(const my_struct &other) 
    //{ 
    // f = other.f; 
    // return *this; 
    //} 
}; 

template<typename Function> 
my_struct<Function> make_struct(const Function &f) 
{ 
    return my_struct<Function>(f); 
} 

int main() 
{ 
    // create some lambda 
    auto lambda = [](int x){return x;}; 

    // make a struct containing a copy of the lambda 
    auto x = make_struct(lambda); 

    // try to assign to the struct, which 
    // presumably assigns to the enclosed lambda 
    x = make_struct(lambda); 

    return 0; 
} 

添加注释的赋值运算符产生一个错误,如所预期:

$ g++-4.6 -std=c++0x test.cpp 
test.cpp: In member function ‘my_struct<Function>& my_struct<Function>::operator=(const my_struct<Function>&) [with Function = main()::<lambda(int)>, my_struct<Function> = my_struct<main()::<lambda(int)> >]’: 
test.cpp:34:25: instantiated from here 
test.cpp:13:5: error: use of deleted function ‘main()::<lambda(int)>& main()::<lambda(int)>::operator=(const main()::<lambda(int)>&)’ 
test.cpp:27:18: error: a lambda closure type has a deleted copy assignment operator 

那么,是否有可能使用lambda成员变量创建可指定类型?这似乎是一个合理的事情想要尝试。例如,考虑将lambda与boost::transform_iterator相结合。

+2

我对移动还不太了解,但有可能移动但不能复制?你可能已经知道了答案,但我对移动设备不了解,所以如果你这样做,请告诉。 –

+0

感谢这个想法,但引入一个移动操作符似乎没有改变错误信息。 –

回答

12

你很近。一个lambda具有一个隐式的复制构造函数,并且可能具有 - 取决于所捕获的值 - 一个隐式移动构造函数。它有一个删除的复制分配操作符。

换句话说,你可以构造它,但你可能不分配它。如果你正在寻找一个通用函数对象,你想使用std::function<>。它将功能模拟为一流的值。


请注意,不可变与赋值不同。当一个lambda被称为可变的,这意味着它的函数调用体可以修改拉姆达的成员(即,功能不const):

int i = 0; 

auto okay = [=](int x) mutable { i += x; }; 
auto error = [=](int x) { i += x; }; 

每个这些是复制施工的和非可分配。

+3

感谢您的解释。这太糟糕了,赋值被删除 - 它似乎使lambda与boost :: transform_iterator不兼容,至少在目前的实现中。 –

+0

请参阅[本答案](http://stackoverflow.com/a/35412456/554283)了解其他解决方法(使用std :: ref,建议的Boost Fit库和建议的Boost范围扩展库)。 –

+0

但如何可以std ::函数做一个lambda的副本? –

相关问题