vendredi 1 mai 2015

temporary lifetime in range-for expression

Consider a simple class A that can be used as a range:

struct A { 
    ~A() { std::cout << "~A "; }

    const char* begin() const {
        std::cout << "A::begin ";
        return s.data();
    }   

    const char* end() const {
        std::cout << "A::end ";
        return s.data() + s.size();
    }   

    std::string s;
};

If I make a temporary A in a range-for, it works exactly as I would hope:

for (auto c : A{"works"}) {
    std::cout << c << ' ';
} 

// output
A::begin A::end w o r k s ~A 

However, if I try to wrap the temporary:

struct wrap {
    wrap(A&& a) : a(std::move(a))
    { } 

    const char* begin() const { return a.begin(); }
    const char* end() const { return a.end(); }

    A&& a;
};

for (auto c : wrap(A{"fails"})) {
    std::cout << c << ' ';
}

// The temporary A gets destroyed before the loop even begins: 
~A A::begin A::end 
^^

Why is A's lifetime not extended for the full range-for expression, and how can I make that happen without resorting to making a copy of the A?

Aucun commentaire:

Enregistrer un commentaire