prevent pass-by-ref of temporary object

c++, pass-by-reference, pass-by-rvalue-reference, rvalue-reference

Solution

If you have to store a `const` reference to some instance of type `B` into your class `A`, then surely you want to be ensured, that lifetime of `A` instance will be exceeded by the lifetime of `B` instance:

B b{};
A a1{b}; // allowed
A a2{B{}}; // should be denied
B const f() { return B{}; } // const result type may make sense for user-defined types
A a3{f()}; // should also be denied!

To make it possible you should explicitly to `= delete;` all the constructor overloadings, which can accept rvalues (both `const &&` and `&&`). For this to achieve you should just to `= delete;` only `const &&` version of constructor.

struct B {};

struct A
{
    B const & b;
    A(B const & bb) : b(bb) { ; } // accepts only `B const &` and `B &`
    A(B const &&) = delete; // prohibits both `B &&` and `B const &&`
};

This approach allows you to prohibit passing to the constructor all kinds of rvalues.

This also works for built-in scalars. For example, `double const f() { return 0.01; }`, though it cause a warning like:

warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]

it still can has effect if you just `= delete;` only `&&` version of constructor:

struct A
{
    double const & eps;
    A(double const & e) : eps(e) {} // binds to `double const &`, `double &` AND ! `double const &&`
    A(double &&) = delete; // prohibit to binding only to `double &&`, but not to `double const &&`
};

double const get_eps() { return 0.01; }

A a{0.01}; // hard error
A a{get_eps()}; // no hard error, but it is wrong!

For non-conversion constructors (i.e. non-unary) there is an issue: you may have to provide `= delete;`-d versions for all the combinatorically possible versions of constructors as follows:

struct A
{
    A(B const &, C const &) {}
    A(B const &&, C const &&) = delete;
    // and also!
    A(B const &, C const &&) = delete;
    A(B const &&, C const &) = delete;
};

to prohibit mixed-cases like:

B b{};
A a{b, C{}};

Problem

I have a class that 'remembers' a reference to some object (e.g. an integer variable). I can't have it reference a value that's destructed immediately, and I'm looking for a way to protect the users of my class from doing so by accident. Is an rvalue-reference overload a good way to prevent a temporary to be passed in? ``` struct HasRef { int& a; HasRef(int& a):a(a){} void foo(){ a=1; } }; int main(){ int x=5; HasRef r1(x); r1.foo(); // works like intended. HasRef r2(x+4); r2.foo(); // dereferences the temporary created by x+4 } ``` Would a private rvalue overload do? ``` struct HasRef { int& a; HasRef( int& a ):a(a){} void foo(){ a=1; } private: HasRef( int&& a ); }; ... HasRef r2(x+1); // doesn't compile => problem solved? ``` Are there any pitfalls I didn't see?

Original source