5

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 :)

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
brads3290
  • 1,926
  • 1
  • 14
  • 20
  • What is `Type::value` supposed to be? How does it support the binary `&` operator? – πάντα ῥεῖ Apr 18 '15 at 13:13
  • Sorry for the confusion. `Type::value` is an object of the class `Datum`, which holds an array of bytes. It's similar to an individual data type. When you apply the binary `&` operator, the operator is applied to all of the bits, just as it would be if you used it on an integer, for example. – brads3290 Apr 18 '15 at 23:01
  • Similar question: https://stackoverflow.com/q/34240794/1971003 – Guy Avraham May 07 '18 at 10:38

2 Answers2

8

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.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
2

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.

brads3290
  • 1,926
  • 1
  • 14
  • 20