Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disallow taking pointer/reference to const to a temporary object in C++ (no C++0X)

I am faced with the following issue. Consider the following class:

//Will be similar to bost::reference_wrapper
template<class T>
class Ref {
public:
  explicit Ref(T& t) : m_ptr(&t) {}
private:
  T* m_ptr;
};

and this function returning a double

double fun() {return 1.0;}

If we now have

double x = 1.0;
const double xc = 1.0;

Ref<double> ref1(x); //OK
Ref<const double> refc1(cx); //OK

good so far, however:

//Ref<double> ref2( fun() ); //Fails as I want it to
Ref<const double> refc2( fun() ); //Works but I would like it not to

Is there a way to modify Ref (the way you prefer) but not the function fun, so that the last line returns a compile-time error? Please notice you can modify the constructor signature (as long as I am able to initialise the Ref as intended).

like image 828
StephQ Avatar asked Nov 09 '10 12:11

StephQ


2 Answers

No, and your code can be broken even with a normal reference. Simply document the fact, that the passed object has to be persistent.

double *x = new double;
Ref<double> ref(*x);
delete x;    
like image 199
Šimon Tóth Avatar answered Nov 12 '22 00:11

Šimon Tóth


You might not like the syntax to use it, but make the constructor take a pointer instead of a reference. You can't take even a const pointer to a temporary.

At least, not without smuggling it through another wrapper that hopefully makes the code Obviously Wrong(TM): template <typename T> T *reftoptr(T &t) { return &t; }

That said, if you're using this the way reference_wrapper is used, your users may actually want to capture temporaries. As long as the Ref object is also a temporary in the same full-expression as the temporary it captures, I think it's OK. So for example,

some_algorithm(iterator, anotherit, static_cast<Ref<const double> >(fun()));
like image 2
Steve Jessop Avatar answered Nov 12 '22 00:11

Steve Jessop