Reputation: 2763
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;
}
Upvotes: 4
Views: 2978
Reputation: 494
So the reason that you are having this error, is that ss.str() returns a const string, not a string. By creating a new string you are creating a non-const variable that is set to the same value as ss.str() and thus can be passed into myFunc(). Making a new string as you have it is probably the easiest way to fix this and still use the function as is.
Upvotes: -1
Reputation: 63775
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.
Upvotes: 4
Reputation: 227410
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 */ }
Upvotes: 7
Reputation: 44043
Since you're not writing to the string inside myFunc
, accept a const reference:
void myFunc (std::string const &msg)
{
std::cout << msg << std::endl;
}
Those can be bound to temporary objects
Upvotes: 1