vendredi 2 décembre 2016

Move constructor trigger unexpectedly by template construcotr (std::function and mini case)

In code below, why F's move ctor is invoked? I ran into this case when I tried to wrap std::function, and surprised to find that my inner functor was moved twice during construction.

#include <iostream>
using namespace std;

struct F {
    F() { cout << "F()" << endl; }
    F(const F &) { cout << "F(const F &)" << endl; }
    F(F &&) {
        cout << "F(F &&)" << endl;
    }

    void operator()() { cout << "F::()()" << endl;}
};

struct I {
#if 0
    // F's move ctor not invoked
    I(F &&) { }
#else
    // F's move ctor invoked, why?
    template<typename FT, typename = void>
    I(FT) { } // Simulate std::function ctor prototype
#endif
};

struct FF {
    FF(F &&f) : _impl(std::move(f)) {} // [line1] Debugger show source here
    I _impl;
};

int main() {
    FF ff = F();
    (void)ff;
    cout << "----" << endl;
    return 0;
}

(using g++ 4.8.x-5.3.x)

gdb shows that the unexpected move ctor called by [line1], but I cannot comprehend it. Could anyone explain it to me?

Besides, in my real case (replace class I by std::function), is there any way to construct wrapper class FF without the inner functor F moved twice?

Aucun commentaire:

Enregistrer un commentaire