Binding r-value to l-value reference is non-standard Microsoft C++ extension

4.5k Views Asked by At

I've been working on a project recently, and I decided to install ReSharper C++ to Visual Studio. When it analysed my code it spat out a bunch of new warnings (apparently I have bad coding habits..). One of them that took me a while to figure out was Binding r-value to l-value reference is non-standard Microsoft C++ extension. I've recreated the warning with the following code:

Type foo(Type t1, Type t2) {
    return Type(t1.value & t2.value);
}

The expression t1.value & t2.value triggers the warning. I understand the second part of the warning, which means that my code only compiles due to a Microsoft extension, and other compilers would refuse to compile it. I'm using an overloaded operator, which returns an object (called Datum) which Type takes as a constructor parameter, as a reference (Type::Type(Datum& dat)).

With some playing around, I managed to make the warning go away by refactoring the code:

Type bar(Type t1, Type t2) {
    Datum datum = t1.value & t2.value;
    return Type(datum);
}

To my understanding, this is functionally equivalent to the code that generated the warning. What I'd really like to know is whether there's something here that I should be aware of, because I'm pretty confused about why one function complains and one doesn't.

I think I've got it figured out. I already had the question typed out, so I'm going to post it with what I found, for the reference of others. I don't really have enough knowledge to go into detail, so please feel free to expand on or correct my answer if it isn't satisfactory :)

2

There are 2 best solutions below

0
brads3290 On

From what I can see, the reason I got such behaviour is because the Type constructor is taking a reference to the Datum object, rather than passing it by value. This causes a warning in Type foo(Type, Type) because the compiler doesn't like taking the reference of expressions, which would be due to the semantics of expression evaluation.

Again, please feel free to elaborate on or correct my findings, as this is simply the result of my experimentation and inference.

0
Mike Seymour On

That's one way to remove the warning: the variable is an lvalue, so can bind directly to the dodgy constructor's reference parameter, while the expression result is an rvalue which can't.

A better solution is to fix the constructor to take its argument by value or constant reference:

Type(Datum dat)         // value
Type(Datum const & dat) // constant reference

Now you can give the argument as either an lvalue or an rvalue.