0

I am making a c++ program and I am stuck on the stage of hosting it on linux. (in fact it is an addon for node.js, but it does not matter now). I get an error when compiling my function on linux (on windows everything is OK).

error: cannot bind non-const lvalue reference of type ‘std::__cxx11::string&’ {aka ‘std::__cxx11::basic_string<char>&’} to an rvalue of type ‘std::__cxx11::string’ {aka ‘std::__cxx11::basic_string<char>’}
         return(merge(messUp3(a.substr(0, (int)(a.size()) / 2)), messUp3(a.substr((int)(a.size()) / 2))));

the problem is exactly here: a.substr(0, (int)(a.size()) / 2). I have managed to fix the error by deleting & from arguments of functions. string merge(string& a, string& b) -> string merge(string a, string b). I think I have some understanding, why it should not work with &, but then I get a complete misunderstanding of why does it work on windows? How do linux and windows gcc compilers differ? Or the problem is somewhere else?

ALEX
  • 55
  • 2
  • 8
  • The function messUp3 has a parameter of the referenced type std::string &. You may not bind the temporary object created like a.substr(0, (int)(a.size()) / 2) to this reference – Vlad from Moscow Aug 24 '20 at 20:42
  • I understand that, but then I do not understand, why does it work on windows without any errors. – ALEX Aug 24 '20 at 20:50
  • 2
    If you are compiling with the MS VS compiler then it has a bug that is called like a language extension.:) – Vlad from Moscow Aug 24 '20 at 20:51
  • 1
    On Windows it's probably not OK, and the compiler is too old and stupid to realize the mistake and reject it at compile time. – user4581301 Aug 24 '20 at 20:51
  • ah.., ok, I understood. Seems like the problem is with the compiler. I will look for an up-to-date version. Hope then it will give the error on windows too. Thanks. – ALEX Aug 24 '20 at 20:54
  • On Windows, try adding `/permissive-` to the compiler command line to report this error. – Paul Sanders Aug 24 '20 at 21:00
  • Just so you know, the code would compile too if instead of removing references (&) you would declare your parameters as constant references. – Aleksander Bobiński Aug 24 '20 at 21:13
  • @Alex I encurage you to play around with how variables can be passed around. https://godbolt.org/z/T359cf – Aleksander Bobiński Aug 24 '20 at 21:23

1 Answers1

0

A reference like std::string & references a value that already exists as an identifiable object in memory (for example by its memory address), which is called an lvalue in C++ terminology.

The return value of a function is a temporary value that has not identity. The compiler is not required to allocate an address for it, which is called an rvalue in C++ terminology.

Thus, you cannot assign an rvalue to an lvalue reference, as the error message says.

(In fact these so-called value categories are a bit more complicated in C++.)

If you replace std::string & by std::string you create a new variable and copy the rvalue into it instead of referencing it, which is ok, because in this case you only read the rvalue instead of referencing it. (To be precise the rvalue will be moved but explaining that is beyond the scope of this answer.)

Your Windows compiler is obviously less strict with the C++ standard by creating a workaround internally instead of pointing out the error. Maybe that compiler has an option to make it more standard-conforming. I'd recommend to turn on such option, particularly if you develop for different platforms, but also to create more clean code.

bjhend
  • 1,538
  • 11
  • 25
  • Handy reading to better understand some of the terminology used: [What are rvalues, lvalues, xvalues, glvalues, and prvalues?](https://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) – user4581301 Aug 24 '20 at 21:10