У меня есть класс с двумя функциями, которые запускают и останавливают коллекцию вещей.Поскольку эти две функции идентичны, за исключением того, что они в конечном счете вызывают функцию запуска или остановки для каждой вещи соответственно, я хотел бы реорганизовать код так, чтобы я переместил тело кода в общую функцию, и мои коллекции начала и остановки вызывают эту передачу вдополнительный параметр, который является функцией, которую они должны вызывать для запуска или остановки.
Естественно, в Интернете есть множество std::bind()
учебных пособий и примеров, но я не нашел здесь ни одной статьи или вопроса / ответа, которые бы охватывали все следующие конкретные ограничения, с которыми я сталкиваюсь:
- Связываемая функция является членом, который усложняет вещи;она также неконстантна
- Связываемая функция также перегружена, поэтому ее следует правильно различать
- В большинстве
std::bind()
примеров используется auto
, но в этом случае мне нужно знатьтип возврата из std::bind()
для передачи в качестве параметра action_widgets()
- Существует два типа bools,
a
& b
, которые фактически являются постоянными и могут быть связаны с функцией, хотяЯ еще не сделал это здесь.Одна вещь за раз.
Вот пример того, чего я пытаюсь достичь:
#include <string>
#include <vector>
#include <functional>
struct Processor {
using WidgetActionFunction = bool(Processor::*)(const std::string&,
bool, bool);
// Function wrapper
using WidgetActionWrapper = std::function<bool(Processor&,
const std::string&, bool, bool)>;
// These functions in reality are tied heavily to the class and are quite
// large. They cannot easily be made static or free.
bool stop_widget(const std::string& key, bool a, bool b) { return true; }
bool start_widget(const std::string& key, bool a, bool b) { return true; }
// Just to make life difficult, there are some overloads, which we're not
// interested in.
bool stop_widget(int event, bool a, bool b) { return true; }
bool start_widget(int event, bool a, bool b) { return true; }
// I created this function because start_widgets() and stop_widgets() were
// identical except that internally they call start_widget() and stop_widget()
// respectively. I want the main body of the code to be here and for the
// appropriate function to be passed in.
void action_widgets(std::vector<std::string>& widgets,
bool a, bool b, WidgetActionWrapper& func) {
std::vector<std::string> valid_widgets;
valid_widgets.reserve(widgets.size());
for (const auto& widget : widgets) {
if (func(*this, widget, a, b)) { // This is where func() gets invoked.
valid_widgets.push_back(widget);
}
}
std::swap(widgets, valid_widgets);
}
void start_widgets(std::vector<std::string>& widgets, bool a, bool b) {
WidgetActionWrapper func =
std::bind(static_cast<WidgetActionFunction>(&Processor::start_widget),
this, std::placeholders::_1, a, b); // compilation fails here.
action_widgets(widgets, a, b, func);
}
void stop_widgets(std::vector<std::string>& widgets, bool a, bool b) {
// Very similar to start_widgets() but calls with bound stop_widget()
// instead.
}
};
int main()
{
return 0;
}
При компиляции я получаю следующую ошибку:
error: conversion from ‘std::_Bind_helper<false, bool (Processor::*)(const std::basic_string<char>&, bool, bool), Processor* const, const std::_Placeholder<1>&, bool&, bool&>::type {aka std::_Bind<std::_Mem_fn<bool (Processor::*)(const std::basic_string<char>&, bool, bool)>(Processor*, std::_Placeholder<1>, bool, bool)>}’ to non-scalar type ‘Processor::WidgetActionFunctor {aka std::function<bool(Processor&, const std::basic_string<char>&, bool, bool)>}’ requested
Ясно, что мой псевдоним оболочки функции не совпадает с тем, что возвращает std::bind()
, но где я ошибся?
Последнее предупреждение или два: поскольку это для корпоративного клиента, я ограниченрешениям на C ++ 11 (хотя решения для пользы других приветствуются), а также, хотя я заинтересован в более простом решении, использующем лямбды, коллеги считают, что это может быть одинаково сложно и в любом случаес технической точки зрения я хотел бы знать, в чем я ошибся.