Как зайти в Даркнет?!
25th January, 01:11
8
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
898
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
951
0
Очень долго работает Update запрос Oracle
27th January, 09:58
916
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
907
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
941
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1725
0
период по дням
25th October, 10:44
3957
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3722
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4614
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4382
0
Помогите пожалуйста решить задачи
24th November, 23:53
6087
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4352
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4398
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Является ли этот код злоупотреблением find_if STL?
Допустим, у меня есть список имен серверов, хранящихся в векторе, и я хотел бы связаться с ними по одному, пока один не ответит успешно. Я думал об использовании алгоритма find_if STL следующим образом:
find_if(serverNames.begin(), serverNames.end(), ContactServer());
Где ContactServer-объект функции предиката.
С одной стороны, существует проблема, поскольку предикат не всегда возвращает один и тот же результат для одного и того же имени сервера (из-за простоя сервера, сетевых проблем и т. д...). Однако один и тот же результат будет возвращен независимо от того, какая копия предиката используется ( т. е. предикат не имеет реального состояния), поэтому исходная проблема с предикатами сохранения состояния в этом случае не актуальна.
Что скажешь?
Я думаю, что пошел бы на это.
Единственное, о чем я бы беспокоился, - это читабельность (и, следовательно, ремонтопригодность) его. Для меня это звучит примерно так:" найдите первый сервер, с которым я могу связаться", что вполне логично.
Возможно, вы захотите переименовать ContactServer , чтобы указать, что это предикат; CanContactServer ? (Но тогда люди будут жаловаться на скрытые побочные эффекты. Хм...)
На мой взгляд, это использование std::find_if немного вводит в заблуждение. Когда я читаю этот фрагмент кода, я не ожидаю никаких побочных эффектов, я просто ожидаю, что будет найдено имя сервера. Тот факт, что результат find_if отбрасывается, также заставит меня задаться вопросом, действительно ли код правильный. Возможно, другое название для предиката сделало бы намерение более ясным, но я думаю, что проблема более фундаментальна.
Для большинства людей find_if -это алгоритм запроса , а не алгоритм модификации . Даже если вы фактически не изменяете значения, которые повторяются, вы изменяете глобальное состояние вашего приложения (в этом случае вы даже, возможно, изменяете состояние удаленных серверов).
В таком случае я бы, вероятно, придерживался ручного цикла, особенно теперь, когда C++11 ввел диапазон на основе циклов:
for (std::string const & name : serverNames)
{
if (ContactServer(name)) break;
}
Другим решением было бы инкапсулировать это в функцию с именем, более четко передающим намерение, например apply_until или что-то в этом роде:
template <typename InputIterator, typename Function>
void apply_until(InputIterator first, InputIterator last, Function f)
{
std::find_if(first, last, f);
// or
// while (first != last)
// {
// if (f(*first)) break;
//
// ++first;
// }
}
}
Но, возможно, я черезмерно-пуристический :)!
Однако один и тот же результат будет возвращен независимо от того, какая копия предиката используется (т. е. предикат не имеет реального состояния), поэтому исходная проблема с предикатами сохранения состояния в этом случае не актуальна.
Однако один и тот же результат будет возвращен независимо от того, какая копия предиката используется (т. е. предикат не имеет реального состояния), поэтому исходная проблема с предикатами сохранения состояния в этом случае не актуальна.
Так в чем же проблема? Объекты функций не обязательно должны иметь состояние. На самом деле лучше всего использовать объекты функций вместо указателей функций в таких ситуациях, потому что компиляторы лучше встраивают их. В вашем случае создание экземпляра и вызов объекта function могут вообще не иметь никаких накладных расходов, так как find_if является шаблоном функции, и компилятор создаст собственную версию для вашего функтора.
С другой стороны, использование указателя функции повлечет за собой опосредование.
В следующей версии стандарта C++ я не смог найти никаких явных ограничений в отношении того, что предикат должен всегда возвращать одно и то же значение для одного и того же ввода. Я заглянул в раздел 25 (пункты 7-10).
Методы, возвращающие значения, которые могут изменяться от одного вызова к другому, как и в вашем случае, должны быть летучими (от 7.1.6.1/11: "volatile-это подсказка к реализации, чтобы избежать агрессивной оптимизации с участием объекта, поскольку значение объекта может быть изменено средствами, не обнаруживаемыми реализацией").
Предикаты "shall not apply any non-constant function through the dereferenced iterators" (пункты 7 и 8). Я полагаю, что это означает, что они не обязаны использовать энергонезависимые методы, и что ваш вариант использования, таким образом, соответствует стандарту.
Если бы формулировка была "predicates should apply const functions..." или что-то в этом роде, то я бы сделал вывод, что функции 'const volatile' не были в порядке. Но это не тот случай.
std::for_each может быть лучшим кандидатом для этого.
1) после копирования в один и тот же объект функции используется на каждом элементе и после обработки всех элементов копия потенциально обновленного объекта функции возвращается пользователю.
2) это также улучшило бы читабельность вызова, на мой взгляд.
Объект функции и вызов for_each будут выглядеть примерно так:
struct AttemptServerContact {
bool server_contacted;
std::string active_server; // name of server contacted
AttemptServerContact() : server_contacted(false) {}
void operator()(Server& s) {
if (!server_contacted) {
//attempt to contact s
//if successful, set server_contacted and active_server
}
}
};
AttemptServerContact func;
func = std::for_each(serverNames.begin(), serverNames.end(), func);
//func.server_contacted and func.active_server contain server information.