samedi 25 février 2017

C++11 move semantic is different between a Lambda and a Function

Take this simple example:

#include <iostream>
struct Data{
    int val = 0;
//Copy ctor
    Data(const Data& a): val(a.val){
        std::cout << "Copy!" << std::endl;
    }
//Move ctor
    Data(Data& a): val(a.val) {
        std::cout << "Move!" << std::endl;
    }
    Data():val(0){}
};

Data a() {
    Data data{};
    std::cout << data.val << std::endl;
    data.val=42;
    return data;
}

auto b=[](){
    Data data{};
    std::cout << data.val << std::endl;
    data.val=42;
    return data;
};

int main(int argc, const char * argv[]) {
    std::cout << "::: Function" << std::endl;
    auto&& d1=a();
    std::cout << d1.val << std::endl;

    std::cout << "::: Lambda" << std::endl;
    auto&& d2=b();
    std::cout << d2.val << std::endl;
    return 0;
}

When it compiles with g++-5 -fno-elide-constructors, the output is as expected:

::: Function
0
Move!
42
::: Lambda
0
Move!
42

The problem is when the Copy ctor is disables, the code compiles fine for function, but not for the lambda:

#include <iostream>
struct Data{
    int val = 0;
//Copy ctor
    Data(const Data&)=delete;

//Move ctor
    Data(Data& a): val(a.val) {
        std::cout << "Move!" << std::endl;
    }
    Data():val(0){}
};

Data a() {
    Data data{};
    std::cout << data.val << std::endl;
    data.val=42;
    return data;
}

auto b=[](){
    Data data{};
    std::cout << data.val << std::endl;
    data.val=42;
    return data;
};
/*
../main.cpp: In static member function ‘static Data<lambda()>::_FUN()’:
../main.cpp:5:1: error: use of deleted function ‘Data::Data(const Data&)’
 };
 ^
../main.cpp:76:5: note: declared here
     Data(const Data& a)=delete;
     ^
*/

int main(int argc, const char * argv[]) {
    std::cout << "::: Function" << std::endl;
    auto&& d1=a();
    std::cout << d1.val << std::endl;

    std::cout << "::: Lambda" << std::endl;
    auto&& d2=b();
    std::cout << d2.val << std::endl;
    return 0;
}

What am I missing here?

Aucun commentaire:

Enregistrer un commentaire