Использование mem_fn вместо mem_fun - PullRequest
0 голосов
/ 22 апреля 2020

Я пытаюсь использовать следующий ответ: String To Lower / Upper в C ++ , но я использую C ++ 17, что означает, что ответ устарел.

Замена bind1st с bind было тривиально, теперь я хотел бы заменить mem_fun на mem_fn, но по некоторым причинам это не так просто для меня.

Я попробовал следующую замену:

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

В результате возникает ошибка "Не найдена перегруженная функция". Почему? Как я могу решить это, если я хочу придерживаться std::transform?

Ответы [ 3 ]

3 голосов
/ 22 апреля 2020

Правильное написание:

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

или на самом деле вам не нужны оба параметра шаблона, только первый:

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

Важная часть, которую вы пропустили: const: это const функция-член, и вам нужен полный тип.

Но вам лучше написать лямбду:

auto greet = [](std::ctype<wchar_t> const& ct, wchar_t c) {
    return ct.toupper(c);
};
3 голосов
/ 22 апреля 2020

Как вы можете видеть в объявлении std::mem_fn, есть два параметра шаблона, первый - сигнатура функции, а второй - тип класса. Проблема в том, что вы только явно указали сигнатуру функции, а не тип класса, что заставляет компилятор выводить ее из аргумента. И аргументом является набор перегрузки std::ctype<wchar_t>::toupper, который вы не разрешили с помощью приведения.

Исправление заключается в явном приведении указателя std::ctype<wchar_t>::toupper к нужному указателю элемента. После этого вам не нужно явно указывать параметр шаблона 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));

Но, конечно, гораздо проще использовать вместо этого лямбду.

3 голосов
/ 22 апреля 2020

Проще избегать std::bind, std::mem_fn и друзей и использовать вместо них лямбды.

Например:

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