2014-12-19 19 views
5

Muszę przekazać funkcję std :: do jakiegoś algorytmu. Rodzaj funkcji jestCzy mogę użyć std :: bind, aby "dołączyć" stan do funkcji?

typedef std::function<bool(const double&)> Condition; 

W najprostszym przypadku, funkcja ta będzie wyglądać następująco

bool simpleCondition(const double& d){return d<0.001;} 

Teraz chcę przekazać tę samą sytuację, ale tylko wtedy, gdy warunek jest spełniony szereg razy w wiersz, funkcja powinna zwracać wartość true. Próbowałem następujący

Mój kompilator nie narzeka i wydaje się działać zgodnie z oczekiwaniami. Jednak naprawdę nie rozumiem, dlaczego (z prostym wskaźnikiem funkcji to nie zadziała, prawda?). Chciałbym również wiedzieć, czy istnieje prostszy sposób na osiągnięcie tego samego.

+0

Z lambda: 'static Condition getRepeatingCondition (Warunek c, int powtórzenia) {int counter = 0; return [=] (double const d) mutable {return if (c (d)) counter + = 1; else counter = 0; return counter> = powtórzenia; }} ' – dyp

+1

Zauważ, że możesz uprościć powyższy kod, zmieniając nazwę' RepeatingCondition :: evalCondition' na 'operator()', upublicznij i użyj 'std :: bind (RepeatigCondition (c, reps), _1) w 'getRepeatingCondition'. – dyp

+0

Czy jest to metoda statyczna z licznikiem statycznym poza pytaniem? To może uprościć nieco sytuację, umożliwiając całkowite opuszczenie obiektu. Uwaga: nie twierdzę, że jest to najlepsze rozwiązanie, ponieważ nie znam innych przypadków użycia. – AndyG

Odpowiedz

8

Czy mogę użyć std::bind, aby "dołączyć" stan do funkcji?

Tak, to jest dokładnie to, do czego służy. Zwraca obiekt (o nieokreślonym typie klasy) zawierający wskaźnik funkcji i wszystkie powiązane argumenty, z wywołaniem funkcji operator() w celu wywołania funkcji z tymi argumentami.

std::function następnie enkapsuluje ten obiekt, umożliwiając jego przepuszczenie i wywołanie bez znajomości jego typu. Ta technika jest znana jako wymazanie typu .

z prostym wskaźnikiem funkcji nie działa, prawda?

Rzeczywiście, potrzebujesz czegoś bardziej skomplikowanego do pracy. To zapewnia std::bind i std::function.

Chciałbym również wiedzieć, czy istnieje prostszy sposób na osiągnięcie tego samego.

lambda jest często bardziej czytelny niż wyrażeniu wiąże:

static Condition getRepeatingCondition(Condition c,int reps){ 
    RepeatingCondition rep(c,reps); 
    return [rep](double d) mutable {return rep.evalCondition(d);}; 
} 
+0

Aby być uczciwym, prosty wskaźnik funkcji mógłby działać, gdyby dodać do niego zmienną statyczną. Na przykład. 'bool rep() {static int counter = 0; return (counter ++> 5);} 'lub coś podobnego. Oczywiście potrzebna jest dodatkowa logika w funkcji, aby zresetować zmienną, jeśli chcesz użyć jej więcej niż raz. – cartographer

+0

@cartographer: To pozwoliłoby tylko na pojedyncze wystąpienie (z dziwnym zachowaniem, jeśli utworzyłeś sekundę). –

+0

Nie powiedziałem, że to dobry pomysł, oczywiście należy preferować podejście podobne do tego, co jest w twojej odpowiedzi, tylko jeśli z jakiegoś powodu nie możesz, istnieją inne sposoby. – cartographer

1

Od @Mike Seymour już wziął podejście lambda, będę zaproponować alternatywę za pomocą funktorów, co może być dobrą alternatywą dla kod w pytaniu:

class RepeatingCondition { 
    Condition m_condition; 
    int  m_counter, m_reps; 

public: 
    RepeatingCondition(Condition c, int reps) 
    : m_condition(c), m_counter(0) , m_reps(reps) { } 

    bool operator()(const double d) { 
     if(m_codition(d)) { 
      m_counter += 1; 
     } else { 
      m_counter = 0; 
     } 

     return (m_counter >= m_reps); 
    } 
}; 

teraz można utworzyć instancję chcesz przy użyciu klasy RepeatingCondition, tak:

RepeatingCondition repCond(checkDouble, 12); 

if(repCond(5.4)) { // calls the operator() overload 
    std::cout << "condition met\n"; 
} 
+0

to jest C++ 11? Po prostu zacząłem lubić nowe fajne rzeczy, ale teraz jestem zmuszony pracować w środowisku, w którym nie mogę używać C++ 11 :( – user463035818

+0

Przepraszamy za późną odpowiedź. Na szczęście dla ciebie, to nie jest C++ 11, więc możesz go używać bez żadnych problemów! –

Powiązane problemy