Home > Software engineering >  Rationale for const ref binding to a different type?
Rationale for const ref binding to a different type?

Time:08-17

I recently learned that it's possible to assign a value to a reference of a different type. Concrete example:

const std::optional<float>& ref0 = 5.0f;
const std::optional<float>& ref1 = get_float();

That's surprising to me. I would certainly expect this to work with a non-reference, but assumed that references only bind to the same type.

I found a pretty good chunk of the c standard which talks about all kinds of ways this works: https://eel.is/c draft/dcl.init.ref#5. But I would appreciate some insight: When is this ever desirable?

A particular occasion where this hurt me recently was this:

auto get_value() -> std::optional<float>{ /* ... */ }
const std::optional<float>& value = get_value();
// check and use value...

I later then changed the return value of the function to a raw float, expecting all uses with a reference type to fail. They did not. Without paying attention, all the useless checking code would have stayed in place.

CodePudding user response:

The basic reason is one of consistency: one would expect each of

void y(X);
void z(const X&);

to accept anything that can be converted to an X, and initializing a local variable has the same semantics.

It also once had a practical value: in C 03, function return values were notionally copied twice:

struct A {};
A f() {
  return A();      // temporary copied into return object
}
void g() {
  A o=f();         // return object copied into o
  const A &r=f();  // refers to return object
}

There was already permission to elide these copies, and in this sort of trivial case it was common to do so, but the reference case at least guaranteed that one copy was avoided.

  •  Tags:  
  • c
  • Related