std::ptr_fun replacement for c++17

Viewed 18247

I am using std::ptr_fun as follows:

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;
}

as presented in this answer.

However this does not compile with C++17 (using Microsoft Visual Studio 2017), with the error:

error C2039: 'ptr_fun': is not a member of 'std'

How can this be fixed?

6 Answers

My answer is similar to the already given answers in this thread. But instead of

int isspace(int c);

function from the standard C library, I am suggesting to use

bool isspace(char c, const locale& loc);

function instantiation from the standard C++ library (http://en.cppreference.com/w/cpp/locale/isspace), which is more type-correct. In this case you don't need to think about char -> unsigned char -> int conversions and about the current user's locale.

The lambda which searches for non-space will looks like this then:

[](char c) { return !std::isspace(c, std::locale::classic()); }

And the full code of ltrim function will look like this:

static inline std::string& ltrim(std::string& s) {
    auto is_not_space = [](char c) { return !std::isspace(c, std::locale::classic()); };
    auto first_non_space = std::find_if(s.begin(), s.end(), is_not_space);
    s.erase(s.begin(), first_non_space);
    return s;
}

You use Lambda as suggested by Nicol Bolas but you can use auto and type will be deduced there, as follow:-

    static inline std::string &ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](auto c) {return 
       !std::isspace(c);}));
    return s;
  }
Related