2

In C++ it is possible to bind a temporary to a const reference:

struct A {};

int main() {
  const A& a = A();
}

Is there any way to disable this for some particular class A so that it would be impossible to bind a temporary of this class to a const reference?

vitaut
  • 49,672
  • 25
  • 199
  • 336
  • Just out of curiocity, why do you need to do that? –  Dec 11 '12 at 16:12
  • I don't need that, just asking out of curiocity =) – vitaut Dec 11 '12 at 16:17
  • The example is silly, but you may want to bind a reference directly to some object, even if the reference is const. – curiousguy Jul 03 '13 at 02:04
  • The can of worms (lifetime extension) that hides behind the mechanism of binding `const &` to rvalues is discussed in a bit more detail here: https://quuxplusone.github.io/blog/2020/03/04/rvalue-lifetime-disaster/ – igel Apr 19 '20 at 16:58

2 Answers2

6

No, and if you need to do this, you're doing something else wrong.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Actually according to C++03 there is a way to do this, but it doesn't work with popular compilers. See my answer for details. – vitaut Dec 16 '12 at 05:57
2

In general there doesn't seem to be a way to do disable binding a temporary to a const reference.

However, to give a substantiated answer, I'd like to cite the C++ 2003 standard:

If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1” is reference-compatible with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementation-defined):

— The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.

— A temporary of type “cv1 T2” [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary. 93)

The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.

So it might seem that this can be achieved in C++03 by making a copy constructor private:

struct A {
  A() {}
 private:
  A(const A&);
};

int main() {
  const A& a = A();
}

However, this will not work with popular compilers. For example, GCC accepts the above code even with -std=c++03 flag. Clang also accepts this code, but with a warning:

test.cc:8:12: warning: C++98 requires an accessible copy constructor for class 'A' when binding a reference to a temporary; was private

So contrary to the standard there is no way to do this.

C++11 no longer require an accessible copy constructor in this case.

vitaut
  • 49,672
  • 25
  • 199
  • 336