Я хочу передать перегруженную функцию в std::for_each()
алгоритм. Например,
class A {
void f(char c);
void f(int i);
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), f);
}
};
Я ожидаю, что компилятор разрешит f()
тип итератора. По-видимому, он (GCC 4.1.2) этого не делает. Итак, как я могу указать, какой f()
я хочу?
Ответы:
Вы можете использовать,
static_cast<>()
чтобы указать, чтоf
использовать в соответствии с сигнатурой функции, подразумеваемой типом указателя функции:Или вы также можете сделать это:
Если
f
это функция-член, то вам нужно использоватьmem_fun
, или для вашего случая, использовать решение, представленное в этой статье доктора Добба .источник
f()
является членом класса (см. Отредактированный пример выше)reinterpret_cast
. Чаще всего я вижу броски в стиле C, используемые для этого. Мое правило состоит в том, что приведение указателей на функции опасно и не нужно (как показывает второй фрагмент кода, существует неявное преобразование).std::for_each(s.begin(), s.end(), static_cast<void (A::*)(char)>(&A::f));
Лямбда на помощь! (примечание: требуется C ++ 11)
Или используя decltype для параметра lambda:
С полиморфными лямбдами (C ++ 14):
Или устраните неоднозначность, удалив перегрузку (работает только для свободных функций):
источник
mem_fn
иbind
, кстати, также C ++ 11). Также, если мы хотим стать действительно педантичными,[&](char a){ return f(a); }
это 28 символов, аstatic_cast<void (A::*)(char)>(&f)
это 35 символов.Почему не работает
Было бы здорово, если бы это было так! Тем не менее,
for_each
это шаблон функции, объявленный как:Шаблон вычета должен выбрать тип для
UnaryFunction
в точке вызова. Ноf
не имеет определенного типа - это перегруженная функция, есть многоf
s с разными типами. В настоящее время нет способаfor_each
помочь процессу вывода шаблонов, указав, чегоf
он хочет, поэтому вывод шаблонов просто не удался. Для успешного вывода шаблона вам нужно проделать дополнительную работу на сайте вызовов.Общее решение для его устранения
Прыгнул сюда через несколько лет, а C ++ 14 позже. Вместо того, чтобы использовать
static_cast
(который позволил бы вывести шаблон успешно, путем «исправления», которыйf
мы хотим использовать, но требует, чтобы вы вручную сделали разрешение перегрузки, чтобы «исправить» правильное), мы хотим заставить компилятор работать на нас. Мы хотимf
привести некоторые аргументы. В наиболее общем виде это:Это много, чтобы напечатать, но такого рода проблемы возникают раздражающе часто, поэтому мы можем просто обернуть это в макрос (вздох):
а затем просто используйте его:
Это будет делать именно то, что вы хотели, чтобы компилятор делал - выполнял разрешение перегрузки для самого имени
f
и просто делал правильные вещи. Это будет работать независимо от того,f
является ли свободная функция или функция-член.источник
Не ответить на ваш вопрос, но я единственный, кто находит
и проще, и короче, чем
for_each
альтернатива, предложенная in silico в этом случае?источник
Проблема здесь, кажется, не в разрешении перегрузки, а в самом деле выводе параметров шаблона . Хотя превосходный ответ @In silico решит проблему неоднозначной перегрузки в целом, при работе с
std::for_each
(или подобным) лучшим решением будет явное указание параметров его шаблона :источник
Если вы не возражаете против использования C ++ 11, вот умный помощник, который похож (но менее уродлив, чем) на статическое приведение:
(Работает для функций-членов; должно быть очевидно, как изменить его для работы с автономными функциями, и вы должны быть в состоянии предоставить обе версии, и компилятор выберет правильную для вас.)
Спасибо Миро Кнейпу за предложение: см. Также https://groups.google.com/a/isocpp.org/d/msg/std-discussion/rLVGeGUXsK0/IGj9dKmSyx4J .
источник
R
, это не выводится. Там также нет упоминания об этом в этом ответе.R
, я даюArgs
.R
иT
выводятся. Это правда, что ответ может быть улучшен. (ВT
моем примере это не так, потому что это не указатель на член, потому что это не сработаетstd::for_each
.)