Can anyone explain this code? I do not understand the working of not1() and ptr_fun()
Can anyone explain the working of this function?
string rightTrim(const string &str)
{
string s(str);
s.erase(find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(), s.end());
return s;
}
I don't know the working of not1()
and ptr_fun()
. Can anyone provide me with a good explanation for this code?
PS: I know, this code removes any white spaces from the end of the string.
Solution 1:
The question is essentially
What is
not1(ptr_fun<int, int>(isspace))
?
Short answer
You should use std::not_fn(isspace)
instead, which clearly states it is a "thing" that expresses the idea that "something is not a space".(¹)(²)
Wordy answer
It is a predicated that asks if its input is not a space: if you apply it to 'a'
you get true
, if you apply it to ' '
, you get false
.
However, one the not in the paragraph above explains the reason why the code has not1
, but it doesn't say anything about ptr_fun
. What is that for? Why couldn't we just write not1(isspace)
?
Long story short, not1
is an old generation helper function which was deprecated in C++17 and removed in C++20. It relies on the argument that you pass to it to have a member type named argument_type
, but isspace
is a free function, not an object of a class providing such a member, so not1(isspace)
is ill formed.
ptr_fun
came to the rescue, as it can transform isspace
in an object which provides the interface that not1
expects.
However, ptr_fun
was deprecated even before not1
, in C++11, and removed in C++17.
The bottom line is therefore that you should not use either of those: you don't need ptr_fun
anymore, and you can use not_fn
as a more usable alternative to not1
. You can indeed just change to not1(ptr_fun<int, int>(isspace))
std::not_fn(isspace)
, which also reads much more like "is not a space".
(¹) By the way, stop using namespace std;
. It's just the wrong thing to do.
(²) Yes, even if you have to stick to C++14, don't use std::not1
. In C++14 you already have generic lambdas, so you can define a quasi-not_fn
yourself (working example):
auto not_fn = [](auto const& pred){
return [&pred](auto const& x){
return !pred(x);
};
};