I'd like to start by saying that yes, I Google'd this problem before coming here, and none of the answers seemed relevant.
I stole the below code from What's the best way to trim std::string?, because for whatever reason, there is no standard c++ trim
function. Using Visual Studio, it compiled fine, and I managed to complete the rest of the project without it giving me any errors.
This morning though, I decided to try compiling the entire project manually (using g++ -std=c++11 *.cpp
), and now suddenly the trim
functions are yielding the following error:
DVD.cpp: In static member function 'static DVD DVD::parseDVD(std::string, std::string)':
DVD.cpp:65:59: error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string<char>&}
from an rvalue of type 'std::basic_string<char>'
std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
It yields similar errors for the other 2 times that trim
is used.
Here is the "stolen" code:
(Utils.h):
static inline std::string& ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
static inline std::string& rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
static inline std::string& trim(std::string& s) {
return ltrim(rtrim(s));
}
And here is the parseDVD
function that the error mentions:
(DVD.cpp):
DVD DVD::parseDVD(std::string dataStr, std::string delimiter) {
DVD newDVD;
int preTitlePos = dataStr.find(delimiter, 0);
int preGenrePos = dataStr.find(delimiter, preTitlePos + 1);
// V Error is here V
std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
std::string rTitle = trim(dataStr.substr(preTitlePos + 1, preGenrePos - preTitlePos - 1));
std::string rGenre = trim(dataStr.substr(preGenrePos + 1));
int parsedID = 0;
//Requirements for a successful parse
//The ID must be fully numeric, and both of the delimiters must have been found
if (parseInt(rID, parsedID) && preTitlePos > -1 && preGenrePos > -1) {
return
newDVD .setID(parsedID)
.setTitle(rTitle)
.setGenre(rGenre);
}
return badDVD;
}
If I remove all of the &
s from the trim functions, it works, but I'd rather it not make copies constantly.
This baffles me because I know the code is sound; not only is it the accepted answer to the above question, but it works fine in Visual Studio.
Your trim()
function is expecting a non-const
reference to a std::string
. When you invoke it like this:
std::string rID = trim(dataStr.substr(0, preTitlePos - 1));
You are invoking it with an rvalue, an unnamed temporary. This will have type const std::string &
, so it is not compatible with the trim()
function. In order to make it work, you would need to assign it to a named variable first:
std::string temp = dataStr.substr(0, preTitlePos - 1);
std::string rID = trim(temp);
On a side note, you seem to be mixing two methods of returning outputs from the trim()
function. Typically, one will either return the function's result (usually by value), or one will modify arguments that were passed to the function by reference. Your functions do both, which is not typical.
I would change them to either take an input argument and return the result by value, or modify the by-reference argument that you pass in (and change their return types to void
).
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