jeudi 3 mars 2016

Storing const reference to an object in class

This sounds like a basic question, but I didn't find any comprehensive answer, so here it is. Consider this code snippet:

struct A {
    const std::string& s;
    A(const std::string& s) : s(s) {}
};

int main() {
    A a("abc");
    std::cout << a.s << std::endl;
    return 0;
}

Demo.

As long as I understand, this is UB. String literal "abc" binds to const std::string& in constructor, creating a temporary string object. It is also bound to reference a.s, and it is destroyed once a is constructed. That is, const reference cannot chain lifetime prolongation. Dangling reference, boom. In this particular case I see no output at all on ideone.com, but anything could happen (remember velociraptors).

Ok, this one is clear. But what if this is actually our very intent: we want to store a const reference to an object? To an existing one, not to temporary? This sounds like a very natural task, yet I came up with only one (almost) natural solution to it. Accepting constructor's argument by std::reference_wrapper instead of by reference:

    A(std::reference_wrapper<const std::string> r) : s(r) {}

Since std::reference_wrapper has deleted constructors from temporaries:

reference_wrapper( T&& x ) = delete;

this works just like expected. However, this is not quite elegant. Another approach I can think of is to accept forwarding reference T&& and to reject everything except const l-value strings with std::enable_if. This is even less elegant, I think.

Any other approaches?

Aucun commentaire:

Enregistrer un commentaire