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?