original.roland
original.roland

Reputation: 700

Using mem_fn instead of mem_fun

I'm trying to utilize the following answer: String To Lower/Upper in C++ but I'm using C++17, which means the answer is deprecated.

Replacing bind1st with bind was trivial, now I'd like to replace mem_fun with mem_fn, but for some reason it's not so simple for me.

I tried the following replacement:

auto greet = std::mem_fn<wchar_t(wchar_t)>(&ctype<wchar_t>::toupper);

Which gives me the "no matching overloaded function found" error. Why? How could I solve it if I wanted to stick to std::transform?

Upvotes: 0

Views: 899

Answers (3)

Barry
Barry

Reputation: 303890

The correct spelling is:

auto greet = std::mem_fn<wchar_t(wchar_t) const, std::ctype<wchar_t>>(
    &std::ctype<wchar_t>::toupper);

or actually you don't need both template parameters, just the first one:

auto greet = std::mem_fn<wchar_t(wchar_t) const>(&std::ctype<wchar_t>::toupper);

The important part you're missing is the const: it's a const member function, and you need the full type.


But you're better off writing the lambda:

auto greet = [](std::ctype<wchar_t> const& ct, wchar_t c) {
    return ct.toupper(c);
};

Upvotes: 3

Acorn
Acorn

Reputation: 26194

It is simpler to avoid std::bind, std::mem_fn and friends, and use lambdas instead.

For instance:

std::transform(in.begin(), in.end(), out.begin(), [&ct](wchar_t c) {
    return ct.toupper(c);
});

Upvotes: 3

Andrey Semashev
Andrey Semashev

Reputation: 10614

As you can see in std::mem_fn declaration, there are two template parameters, the first one is the function signature, and the second one is the class type. The problem is that you only explicitly specified function signature and not the class type, which makes the compiler have to deduce it from the argument. And the argument is an overload set std::ctype<wchar_t>::toupper, which you did not resolve with a cast.

The fix is to explicitly cast the std::ctype<wchar_t>::toupper pointer to the member pointer you want. After that you don't need to explicitly specify the template parameter of std::mem_fn.

using toupper_t = wchar_t (std::ctype<wchar_t>::*)(wchar_t) const;
auto greet = std::mem_fn(static_cast< toupper_t >(&std::ctype<wchar_t>::toupper));

But, of course, it is much easier to just use a lambda instead.

Upvotes: 3

Related Questions