Заменить значения вызова для std::function
Я сохранил std::function
, которые являются результатами std::bind
в списке:
typedef std::pair<int, std::function<void(HDC)>> myPair;
std::list<myPair> *paintJobs;
paintJobs = new std::list<myPair>();
Я тогда добавляю что-то вроде этого:
int id = 1;
int x = 0;
int y = 0;
int width = 100;
int height = 100;
int r = 255;
int g = 0;
int b = 0;
std::function<void(HDC)> func = std::bind(&Window::drawRect, this, std::placeholders::_1, x, y, width, height, r, g, b);
paintJobs->push_back(std::make_pair(id, func));
В моем методе рисования я просматриваю список и вызываю все добавленные функции. Эта часть работает хорошо.
Но теперь я хочу заменить, например, цвет (r, g и b):
void changeColor(int id, int r, int g, int b) {
for(auto elem = paintJobs->begin(); elem != paintJobs->end(); ++elem) {
if(elem->first == id){
//change the 6th, 7th and 8th parameter of elem->second
}
}
}
Моя другая идея состояла в том, чтобы вставить новую запись и скопировать старые значения, но есть другая проблема: получение связанных значений.
Так как же я могу заменить связанные значения параметров или получить значения других?
2 ответа
Магазин std::function<void(HDC, int r, int g, int b)>
(или эквивалент) вместо std::function<void(HDC)>
, Также хранить struct {int r,g,b;}
,
struct rgb { int r,g,b; };
struct rgb_func {
rgb color;
std::function<void(HDC, rgb)> f;
void operator()(HDC hdc)const{
return f(hdc, color);
}
};
std::function<void(HDC, rgb)> func =
[this, x, y, width, height](HDC hdc, rgb color)->void
{
this->drawRect( hdc, x, y, width, height, color.r, color.g, color.b );
};
paintJobs->push_back(std::make_pair(id, rgb_func{ {r,g,b}, func }));
затем изменить его:
void changeColor(int id, int r, int g, int b) {
for(auto elem = paintJobs->begin(); elem != paintJobs->end(); ++elem) {
if(elem->first == id){
elem->second.color = {r,g,b};
}
}
}
обратите внимание, что тип second
больше не std::function<void(HDC)>
, но она конвертируема в std::function<void(HDC)>
но не от этого. Такое преобразование может привести к скромным накладным расходам; использование auto&
бы избежать этого в этом случае.
Код не проверен; дизайн это звук. Там, наверное, тпёсь. я бы сделал rgb
быть немного лучше (например, гарантировать обнуление или что-то еще).
Я использовал лямбду вместо std::bind
, так как std::bind
сбивает с толку и был в значительной степени устарел, когда он был добавлен в std
,
Как в сторону
void changeColor(int id, int r, int g, int b) {
for(auto& elem:*paintJobs) {
if(elem.first == id){
elem.second.color = {r,g,b};
}
}
}
намного менее грязный
Вы можете сделать решение, подобное следующему:
- Храните ваши связанные параметры в другом месте.
- Перейдите к вашей функции
std::bind(f, ..., std::ref(param)...)
Идея состоит в том, чтобы иметь возможность изменять параметры:
std::function<void(HDC)> func = std::bind(&Window::drawRect, this, std::placeholders::_1, std::ref(x)...
Теперь вы можете изменять параметры извне, при повторном вызове функции будут использоваться новые значения.
Другим решением будет изменить подпись вашего std::function
взять параметры для каждого звонка.