I am using std::stringstream to construct a string and then attempting to pass the completed string as a reference to a function which takes as a parameter a std::string&.
I am getting a compilation error on GCC:
../src/so.cpp:22:21: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘std::basic_stringstream<char>::__string_type {aka std::basic_string<char>}’
../src/so.cpp:12:6: error: in passing argument 1 of ‘void myFunc(std::string&)’
make: *** [src/so.o] Error 1
The same code is compiling on Windows VS2012, but fails on my Linux and Android builds. What is the reason for this?
I can work around the issue by temporarily assigning ss.str() to a temporary std::string and then passing that string by reference, but this seems slightly silly. What is the correct way to do this cleanly?
#include <iostream>
#include <sstream>
void myFunc (std::string& msg)
{
std::cout << msg << std::endl;
}
int main (void)
{
std::stringstream ss;
ss << "this is a test";
myFunc (ss.str()); // Fails
std::string s = ss.str();
myFunc (s); // Pass
return 0;
}
The issue is that myFunc
takes a non-const lvalue reference. stringstream::str()
returns a string by value. You cannot bind a temporary to a non-const lvalue reference in standard C++, but VS has an "extension" that allows this. That is the reason it compiles on VS and not on other compilers.
const
lvalue references, on the other hand, can bind to rvalues. So modifying your function thus would make it work:
void myFunc (const std::string &msg) { /* as before */ }
Change this:
void myFunc (std::string& msg)
to this:
void myFunc (const std::string& msg)
// ^^^^^ this will allow temporaries like ss.str()
There are versions of Visual Studio that will foolishly allow a temporary to bind to a non-const reference. It is dangerous and not valid C++, however.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With