-1
inline string& rtirm(string& s)
{
    s.erase(s.find_last_not_of(' ') + 1);
    return s;
}

const char* buf = " abc ";
string s_trim = rtirm(string(buf));

This code has been working well until I upgraded visual studio to 2022 and with C++20.

Error C2664 'std::string &rtirm(std::string &)': cannot convert argument 1 from 'std::string' to 'std::string &'

I clearly understand the reason -- a reference can't refer to a tempoary object. But this make the code more complicated. Do I have to define a variable before calling rtirm?

string temp{buf};
string s_trim = rtirm(temp);
273K
  • 29,503
  • 10
  • 41
  • 64
Zhang
  • 3,030
  • 2
  • 14
  • 31
  • 1
    As an aside, this has nothing to do with changes in the C++20 standard, but rather that the newer compiler is stricter by default. See the [/permissive](https://learn.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-170) option. – BoP Feb 22 '23 at 09:27
  • 1
    iirc msvc allows to bind temporaries to non-const references as non standard extension in certain circumstances, but I dont know about any details and neither does it explain why it stops working. Though anyhow the code should be fixed – 463035818_is_not_an_ai Feb 22 '23 at 09:31
  • https://godbolt.org/z/z9PTbbM55 so now MSVC behaves like other compilers. Note warring is filed, so if you treat warnings as errors the in older version it will be same. – Marek R Feb 22 '23 at 10:07

2 Answers2

0
inline string& rtirm(string& s)
{
    s.erase(s.find_last_not_of(' ') + 1);
    return s;
}

inline string rtrim(string&& s)
{
    s.erase(s.find_last_not_of(' ') + 1);
    return s;
}

void test(){
    const char* buf = "    abc    ";
    string sTemp{ buf };
    rtrim(sTemp);
    
    string s_trim = rtrim(string(buf));
}

I prefer this, adding a rvalue-reference version, that makes both reference and rvalue-reference arguments working.

Zhang
  • 3,030
  • 2
  • 14
  • 31
0

yes, you have to define a variable and then call rtrim using it instead of temporary object.