Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Как передать функтор в метод ждущий указатель? |
Автор: EvilsInterrupt 7.12.2012, 10:42 | ||
Есть код:
Я ожидаю что передавая объект, автоматически вызовется operator(). Мне нужно чтобы класс парсера вызвал этот оператор, а тот в свою очередь поменял состояние объекта,запомнив переданную ошибку. Прав ли я? Или все не так просто и функтор не может менять состояние объекта? Если да, то мне похоже нужно юзать static метод, а в нем писать либо статическую переменную или обращение к синглтону или другую магию... |
Автор: volatile 7.12.2012, 12:33 | ||
Я не заметил что у вас в парсере хранится не объект, а указатель на функцию. Зачем? operator(), имеет совсем другую сигнатуру. вам нужно хранить либо указатель на сам объект ErrorHadler, либо ссылку на него. (что я и предложил в 1-ом способе) |
Автор: volatile 7.12.2012, 12:51 | ||
Еще у вас опечатка Короче вот весь текст целиком : ![]()
|
Автор: EvilsInterrupt 7.12.2012, 15:07 | ||||
volatile, Ок, спасибо!
Потому что в реальной ситуации, а я сделал уменьшенный пример реальной ситуации, пользователь может воспользоваться функции нотификации об ошибках идущим по умолчанию с классом парсером. Но Может также задать и свою функцию. Мне же хочется передавать и внешне созданный функтор, т.к. копить ошибки куда удобнее. Если точнее сформулировать требования к этой ситуации, то нужно уметь передавать : 1) Как указатель на обычную функцию 2) Так и внешне созданный объект класса с переопределенным operator(), который позволит удобным способом накапливать ошибки Пока склоняюсь к шаблонному решению,на подобии того что сделано в std::for_each.
|
Автор: mes 7.12.2012, 20:03 |
EvilsInterrupt, boost::function в комплекте с boost::bind сделают мечты реальностью )) для С++11 и буста не надо..все в коробке)) |
Автор: EvilsInterrupt 8.12.2012, 10:55 | ||
mes, Полностью согласен по поводу буста, в своих проектах(домашних) применяю его и по поводу новых технологий в виде С++11 тоже согласен, но не всегда можно применить все что душе хочется :( Попробую сформулировать проблему еще раз, а то кажется меня не понимают ;) Вообщем мне надо на обычном С++03 мою проблему решить, т.к. он MSVS 2008. На псевдокоде то что я хочу получить выглядит примерно так:
В существующем коде(моих тулзах) применяются иногда свои функции аналоги defErrorHandler, их переписать нет желания. Слишком много моих тулзов, которые я уже оттестировал и отладил может поломаться. Но в текущей тулзе, которую сейчас пишу, мне куда удобней написать класс функтор. Возникает вопрос: Как имея: 1) Обычные функции подобные defErrorHandler 2) Имея класс функтор Подавать в explicit-конструктор класса парсера как п.1 так и п.2 ? При этом текущие тулзы имеют семантику использования парсера в таком виде: Parser parser1(), т.е. обработчик по умолчанию. |
Автор: volatile 8.12.2012, 18:07 | ||||||
EvilsInterrupt, а что запрещает буст::функшен использовать? там действительно все очень удобно. Кроме-того у вас помимо основной проблемы, еще много "шума".
defErrorHandler - вовсе не обычная функция, это функция-мембер. а это 2 большие разницы. Кроме-того, у вас функтор, используется не в СТЛ-овском смысле. Он передается как ссылка на существующий "объект с состоянием", и не очень понятно, это требование, или просто побочный эффект.
Если обычная функция, это действительно обычная функция, а передача функтора в виде ссылки на существующий "объект с состоянием"- требование, то можно сделать так:
Читайте комменты в коде. (если бы не вышеизложенные требования, то можно было бы проще) Добавлено через 1 минуту и 9 секунд Если опять не то, то постарайтесь упростить код вопроса, убрав все лишнее. Как я уже говорил, у вас много лишнего "шума", причем не понятно, что из этого требование, а что случайный/ошибочный код. |
Автор: volatile 8.12.2012, 18:29 | ||
Да, и забыл привести вывод:
Если обычная функция, это не обычная функция ![]() |
Автор: EvilsInterrupt 8.12.2012, 23:03 | ||
volatile,
Весь этот "огород" когда-то мне показался вполне логичным на мое желание дать возможность назначить функцию обработчика ошибки, т.к. обработчик предоставляемый по умолчанию приводил к бросанию исключений в случае обнаружения ошибок, что не во всех моих тулзах было нужно. Спасибо за внимание, ну и раз Вы уж упомянули "было бы проще". Хотелось бы Ваше проектное решение увидеть,если конечно не затруднит ) |
Автор: volatile 8.12.2012, 23:18 |
EvilsInterrupt, ну это подошло или нет? |
Автор: EvilsInterrupt 8.12.2012, 23:35 |
volatile, Да, Спасибо! Пока не вижу ничего чтобы сказать "не подходит". Все-таки хотелось бы увидеть решение более опытного товарища ;) |
Автор: mes 8.12.2012, 23:52 |
вот скажите причем тут ехплицит ? зачем отвлекаться на несущественные детали ? Добавлено через 3 минуты и 13 секунд если готовое использовать не получается попробую показать ход мыслей, для решения подобных задач )) |
Автор: mes 9.12.2012, 00:27 | ||
итак мы должны для одного и то же действия использовать полиморфизм, при этом, забегая вперед, имеются, как минимум, две возможности.. посредством виртуальных функций или "привязыванием", но для общего представления это не важно.. также, нам нужно это сделать, чтоб для пользователя было прозрачным.. значит нужен враппер, и так как враппер долже иметь состояние, значит используем функтор.. итого две подзадачи.. 1. адаптация функции/функтора 2. сокрытие под удобным интерфейсом |
Автор: mes 9.12.2012, 00:51 | ||||||
допустим интерфейс имеет такую структуру
тогда нам нужна пару адаптеров, один для функции другой для функтора..
для функтора аналогично.. Добавлено через 9 минут и 43 секунды теперь обернем интерфейс
|
Автор: mes 9.12.2012, 01:07 |
для функтора поставил многоточие, потому что зависит от того, какой концепт вы выбирете для него.. можно, например, ограничить функторы наследованных от интерфейса, тогда в последний нужно будет добавить виртуальную функцию клонирования.. либо прибегнуть к помощи шаблонов и организовать привязку.. |
Автор: mes 9.12.2012, 01:27 |
итого , самый простой способ: описать базовый функтор, от которого отнаследовать адаптер для простой функции. все остальные функторы должны наследоваться от этой базы.. базовый функтор должен уметь быть клонированым, что будет использовано оберткой для успешного копирования.. помимо этого можно добавить старатегию хранения : обьект посредник, между оберткой и нтерфейсом, который выбирает перемещать ли интерфейс, или клонировать.. это поможет выбирать по ссылке ли передовать функтор или по значению.. |
Автор: EvilsInterrupt 26.12.2012, 22:52 |
Размышляя над моей текущей ситуацией по поводу обработки ошибок в моих проектах, которая привела к этому топику и мне кажется ее можно решить куда изящней. Поэтому поставлю задачу несколько по другому, чтобы увидеть мнение других разработчиков на С++. Условия задачи:
Суть задачи: Придумать способ обработки ошибок в коде класса парсера CustomFormatParser и при этом дать возможность пользователю класса влиять на выбор стратегии обработки, одну из следующих двух:
Мои мысли привели к тому что : Надо реализовывать Event-driven , т.е. вариант обработки ошибки с использованием callback-функции в качестве обработчика ошибки. Реализовать обработчик ошибки по умолчанию, задаваемый в конструкторе класса парсера как параметр по умолчанию. Затем в коде класса парсера вызывается обработчик ошибки, который задан по умолчанию или реализован и передан пользователем в параметре конструктора. Этот обработчик возвращает статус : "продолжить работу дальше или нет?" имея подобный ответ мы либо бросаем исключение, либо продолжаем работу парсера дальше, но запоминаем информацию об ошибке. Но возможно решение принятое мною не особо и красиво, хочется увидеть мысли других. |
Автор: baldina 27.12.2012, 00:43 | ||
EvilsInterrupt,
диктуется объективными причинами, или это просто желание сделать в более общем виде? |
Автор: EvilsInterrupt 27.12.2012, 08:48 | ||
Диктуется причинами. Чаще пишу такие типы приложений когда работа с попорченным файлом не имеет смысла. Но есть и другие типы приложений, которые анализируют и выдают информацию о файле им-то как раз и нужно чтобы приложение работало дальше даже с попорченным файлом |
Автор: mes 27.12.2012, 15:34 | ||
это если простой вариант с возвращением статуса окончания операции не подходит.
почему эта стратегия должна быть частью логики парсера ? продолжение работы после исключения - это никак не внутренняя ответственность обьекта, именнуемого парсер.. спецификация постановки вопроса ограничивает детализацию ответа.. Вы спрашиваете не о решение задачи как таковом, а о том, как притянуть то, что Вам хочется, но, чтоб получилось как оно всем надо.. ![]() |