Comments 20
Недостает рассказа о том, почему реализация является наивной.
Меня вообще всегда пугает, когда вижу реализацию чего-либо с комментарием вроде «простейший вариант, наивная реализация», без какого-либо объяснение что не было учтено. Хорошо, если уже знаешь в чем о чем идет речь. Но когда сталкиваешься впервые, чувствуешь себя несколько глупым.
В данном случае, возможно, предполагается отсутствие поддержки std::ref/cref, а так же свой вариант кортежей, который в свою очередь так же требует пояснений чем он наивен. На хабре были статьи о реализации кортежей на C++, можно поискать.
В данном случае, возможно, предполагается отсутствие поддержки std::ref/cref, а так же свой вариант кортежей, который в свою очередь так же требует пояснений чем он наивен. На хабре были статьи о реализации кортежей на C++, можно поискать.
Приведите, пожалуйста, пример из реальной жизни, когда этот std:: bind действительно нужен.
В задачах вызова callback-ов (функциональных объектов, которые необходимо вызвать при условии, что произошло какое-то событие). Часто на практике в качестве callback-объектов используют результат std::(или boost::)bind. Конечно, с выходом с++11 во многих случаях теперь можно обойтись использованием лямбда-функций.
Можно уточнить, что bind нужен не просто для вызова callback'ов, а когда необходимо передать в callback дополнительные параметры. Проблема в том, что сигнатура callback-функции обычно жёстко задана, так что если нужно передать что-то ещё в неё, приходится опираться либо на какие-то переменные в более широком scope (поля класса или даже глобальные переменные, хоть это и фу-фу-фу), либо биндиться. Первый случай имеет ограниченное применение: что если потребуется вызвать два и более одинаковых коллбэка сразу, например, запустить два процесса чтения каких-то данных из сокетов, а по завершении функция чтения вызовет один и тот же коллбэк? Часто нужно как-то различать, откуда именно был вызван коллбэк, чтение какого именно сокета завершено, чтобы отреагировать верно, а переменная у нас лишь одна.
В этом случае bind спасает, мы делаем коллбэк с бо́льшим числом параметров, чем нужно для стандартной/библиотечной/чужой функции, биндим к нашим собственным параметрам некоторые значения, а те, про которые «знает» чужая функция, заменяем placeholder'ами. Получается такая себе rvalue-функция, которая сигнатурно совпадает с ожидаемой, но при вызове подставит наши заранее привязанные значения к нужным параметрам и вызовет уже нашу расширенную функцию.
Короче говоря, это такой сигнатурный адаптер, только не для классов, а для функций. По крайней мере, мне в голову не приходят другие применения.
В этом случае bind спасает, мы делаем коллбэк с бо́льшим числом параметров, чем нужно для стандартной/библиотечной/чужой функции, биндим к нашим собственным параметрам некоторые значения, а те, про которые «знает» чужая функция, заменяем placeholder'ами. Получается такая себе rvalue-функция, которая сигнатурно совпадает с ожидаемой, но при вызове подставит наши заранее привязанные значения к нужным параметрам и вызовет уже нашу расширенную функцию.
Короче говоря, это такой сигнатурный адаптер, только не для классов, а для функций. По крайней мере, мне в голову не приходят другие применения.
Вообще-то callback функции — это из С. В С++ их заменили виртуальные функции. Кто мешает передать указатель на базовый класс, с виртуальной функцией перекрытой в производном классе?
Насчет замены аргументов — это вообще жесть. Если взять первый пример в статье, где функция f_sum( 5, 7 ) вернет 10 — то человек, который будет поддерживать вашу программу будет о вас, скажем мягко, не очень высокого мнения.
Именно так сделано в Java. Но это более громоздко, зачем создавать экземпляр класса, если от него требуется выполнить всего лишь одну функцию? Лишние накладные расходы. А коллбэки понятно оформляются через std::function. Язык, в конце концов, мультипарадигменный, так что функциональный стиль тоже имеет право на жизнь.
Нет callback это не только из С, это из всего)
Иногда гораздо проще в С++ использовать именно этот подход, чем завязываться на базовый класс в параметре и знание его методов. Во многих случаях это не только лишне, но и тяжело реализовать, например при передачи асинхронного сообщения. зачем вам знать структуру и особенности реализации (объектной иерархии в частности) получателя события? Вам дали callback, дергайте за него «и не задавайте лишних вопросов») Получатель события сам сформирует и подготовит правильный callback, и вот тут как раз пригодится bind или анонимная лямбда. Что лучше из этого, вопрос дискуссионный) наверно надо в каждом конкретном случае решать отдельно.
Иногда гораздо проще в С++ использовать именно этот подход, чем завязываться на базовый класс в параметре и знание его методов. Во многих случаях это не только лишне, но и тяжело реализовать, например при передачи асинхронного сообщения. зачем вам знать структуру и особенности реализации (объектной иерархии в частности) получателя события? Вам дали callback, дергайте за него «и не задавайте лишних вопросов») Получатель события сам сформирует и подготовит правильный callback, и вот тут как раз пригодится bind или анонимная лямбда. Что лучше из этого, вопрос дискуссионный) наверно надо в каждом конкретном случае решать отдельно.
А чем плох вариант оборачивания в анонимную лямбду? ИМХО, на порядок нагляднее всяких байндов с плейсхолдерами. По производительности — одинаково. По памяти скорее всего тоже.
С чего вы взяли? Нельзя просто так такими заявлениями бросаться — вам ведь могут поверить. Надо измерять.
Вот, Stephan T. Lavavej, с вами не согласен.
Окей, в теле «горячего» цикла лучше использовать bind, но обычно читаемость предпочтительна микроскопическому выигрышу в производительности там, где это не нужно.
Медленно работающая программа лучше быстрой, но глючной.
Медленно работающая программа лучше быстрой, но глючной.
Вот сколько пользовался functional — а bind ни разу не понадобился. Можно же всё в лямбду завернуть, читаемость и простота написания на порядок выше.
трудно найти такого программиста на C++, который никогда не применял в своем коде boost::bind
в вашем ареале обитания?
Sign up to leave a comment.
Наивная реализация std::bind(boost::bind)