2017-02-09 4 views
1

I std::function gespeichert haben, die Ergebnisse von std::bind, in einer Liste sind:ersetzen Aufruf Werte für std :: function

typedef std::pair<int, std::function<void(HDC)>> myPair; 

std::list<myPair> *paintJobs; 
paintJobs = new std::list<myPair>(); 

ich dann füge ich etwas wie folgt aus:

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)); 

In meinem Malmethode Ich gehe durch die Liste und rufe alle Funktionen auf, die ich hinzugefügt habe. Dieser Teil funktioniert gut.

Aber jetzt, ich möchte zum Beispiel die Farbe wechseln (die r, g und 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 
     } 
    } 
} 

Meine andere Idee, einen neuen Eintrag einzufügen war und das Kopieren der alten Werte, aber es ist die anderes Problem: Erhalten der gebundenen Werte.

Also wie kann ich die gebundenen Werte der Parameter ersetzen oder die Werte der anderen erhalten?

+2

[OT]: 'Std :: Liste * PaintJobs;' ...Unbezahlter Zeiger, 'std :: list paintJobs;' ist wahrscheinlich, was Sie wollen. – Jarod42

+0

Es ist ein bisschen komplizierter in einer eingebetteten Klasse, also der Zeiger –

+0

Wenn Sie die "Mitglieder" ändern wollen, dann sollten Sie einen Funktor erstellen und Zugriff darauf gewähren. Dann können Sie diesen Funktor anstelle einer 'std :: function' speichern. – NathanOliver

Antwort

1

Speichern Sie eine std::function<void(HDC, int r, int g, int b)> (oder gleichwertig) anstelle einer std::function<void(HDC)>. Speichern Sie auch eine 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 })); 

dann, es zu ändern:

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}; 
    } 
    } 
} 

zur Kenntnis, dass die Art des second nicht mehr ein std::function<void(HDC)> ist, aber es ist umwandelbar zu einem std::function<void(HDC)> aber von ihm nicht. Eine solche Umwandlung könnte zu einem geringen Aufwand führen. Verwendung von auto& würde es in diesem Fall vermeiden.

Code nicht getestet; Design ist Klang. Es gibt wahrscheinlich tpyos. Ich würde rgb ein bisschen netter machen (wie, Garantie Nullstellung oder was auch immer).

Ich verwendete Lambda anstelle von std::bind, weil std::bind ist verwirrend und war ziemlich veraltet, wenn es std hinzugefügt wurde.

Als Neben

void changeColor(int id, int r, int g, int b) { 
    for(auto& elem:*paintJobs) { 
    if(elem.first == id){ 
     elem.second.color = {r,g,b}; 
    } 
    } 
} 

ist viel weniger chaotisch.

+0

Es funktioniert, nach ein bisschen fiedeln –

0

Sie könnten eine Lösung wie folgt tun:

  1. Speichern Sie Ihre gebundenen Parametern an anderer Stelle.
  2. Pass auf Ihre Funktion std::bind(f, ..., std::ref(param)...)

Die Idee ist in der Lage sein, die Parameter ändern:

std::function<void(HDC)> func = std::bind(&Window::drawRect, this, std::placeholders::_1, std::ref(x)... 

Jetzt können Sie die Parameter von außen ändern, wenn die Funktion erneut aufgerufen wird, wird es verwenden die neuen Werte.

Eine andere Lösung wäre, die Signatur Ihres std::function zu ändern, um die Parameter für jeden Anruf zu übernehmen.

Verwandte Themen