2011-12-12 36 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的副本? –

相關問題