Używanie generycznych obiektów STD::function z funkcjami składowymi w jednej klasie

Dla jednej klasy chcę przechowywać niektóre wskaźniki funkcji do funkcji Członkowskich tej samej klasy w jednym map przechowującym std::function obiektach. Ale ja na początku z tym kodem się nie zgadzam:

class Foo {
    public:
        void doSomething() {}
        void bindFunction() {
            // ERROR
            std::function<void(void)> f = &Foo::doSomething;
        }
};

Otrzymuję error C2064: term does not evaluate to a function taking 0 arguments w xxcallobj w połączeniu z dziwnymi błędami tworzenia szablonu. Obecnie pracuję na Windows 8 z Visual Studio 2010/2011 i na Win 7 z VS10 też się nie udaje. Błąd musi być oparty na jakichś dziwnych regułach C++, których nie przestrzegam.

EDIT: I do NOT use boost. Jest to C++11 zintegrowany z kompilatorem MS.

Author: Max, 2011-09-28

3 answers

Niestatyczna funkcja członka musi być wywołana z obiektem. Oznacza to, że zawsze pośrednio przekazuje "ten" wskaźnik jako swój argument.

Ponieważ twoja podpis std::function Określa, że twoja funkcja nie pobiera żadnych argumentów (<void(void)>), musisz związać pierwszy (i jedyny) argument.

std::function<void(void)> f = std::bind(&Foo::doSomething, this);

Jeśli chcesz powiązać funkcję z parametrami, musisz podać symbole zastępcze:

using namespace std::placeholders;
std::function<void(int,int)> f = std::bind(&Foo::doSomethingArgs, this, _1, _2);

Lub, jeśli twój kompilator obsługuje lambdy C++11:

std::function<void(int,int)> f = [=](int a, int b) {
    this->doSomethingArgs(a, b);
}

(nie mam Kompilator C++11 w zasięgu ręki teraz , więc nie mogę tego sprawdzić.)

 206
Author: Alex B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-17 12:30:00

Albo potrzebujesz

std::function<void(Foo*)> f = &Foo::doSomething;

Tak, że można go wywołać na dowolnej instancji, lub trzeba powiązać konkretną instancję, na przykład this

std::function<void(void)> f = std::bind(&Foo::doSomething, this);
 59
Author: Armen Tsirunyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-17 09:59:30

Jeśli chcesz zapisać funkcję member Bez instancji klasy, możesz zrobić coś takiego:

class MyClass
{
public:
    void MemberFunc(int value)
    {
      //do something
    }
};

// Store member function binding
auto callable = std::mem_fn(&MyClass::MemberFunc);

// Call with late supplied 'this'
MyClass myInst;
callable(&myInst, 123);

Jak wyglądałby Typ pamięci bez auto ? Coś takiego:

std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable

Można również przekazać tę funkcję do standardowego wiązania funkcji

std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call

Past and future notes: starszy interfejs STD::mem_func istniał, ale od tego czasu był przestarzały. Istnieje propozycja, post C++17, Aby wskaźnik do member funkcje wywoływalne . To byłoby bardzo mile widziane.

 7
Author: Greg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-07 06:38:37