Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove a std::function<void()> in vector?

Tags:

c++

I'm trying to create C# event in c++ for my game engine. I'm implementing the event system now but I don't know how to remove a std::function in a vector. Am I using the correct list?

I'm quite new in C++ but I'm a C# programmer for 10 years now. Is this possible in C++?

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>

struct Delegate {
    std::vector<std::function<void()>> funcs;

    template<class T> void operator+=(T mFunc)
    {
        funcs.push_back(mFunc);
    }

    template<class T> void operator-=(T mFunc)
    {
        // How?
        //funcs.erase(std::remove(funcs.begin(), funcs.end(), mFunc), funcs.end());
    }

    void operator()() {
        for (auto& f : funcs) f();
    }
};

void fun1()
{
    std::cout << "hello, ";
}

void fun2()
{
    std::cout << "Delete";
}

void fun3()
{
    std::cout << "world!" << std::endl;
}

int main() {
    Delegate delegate;
    delegate += fun1;
    delegate += fun2;
    delegate -= fun2;
    delegate += fun3;
    delegate();
}
like image 559
Hey Avatar asked Feb 13 '20 16:02

Hey


People also ask

How to remove std in c++?

std::remove, std::remove_if in c++ It is defined in <algorithm> library. It removes value from range. Transforms the range [first,last) into a range with all the elements that compare equal to val removed, and returns an iterator to the new end of that range.

What is std:: function in c++?

C++ Library - <functional> Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.

What is a function pointer in c?

CServer Side ProgrammingProgramming. Function Pointers point to code like normal pointers. In Functions Pointers, function's name can be used to get function's address. A function can also be passed as an arguments and can be returned from a function.

How do you return a vector STD?

In C++11, this is the preferred way: std::vector<X> f(); That is, return by value. With C++11, std::vector has move-semantics, which means the local vector declared in your function will be moved on return and in some cases even the move can be elided by the compiler.


2 Answers

If you are willing to limit Delegate to only using function pointers the you can do it with what you have. That would look like

struct Delegate {
    std::vector<void(*)()> funcs;

    template<class T> void operator+=(T mFunc)
    {
        funcs.push_back(mFunc);
    }

    template<class T> void operator-=(T mFunc)
    {
        funcs.erase(std::remove(funcs.begin(), funcs.end(), mFunc), funcs.end());
    }

    void operator()() {
        for (auto& f : funcs) f();
    }
};

If you don't want to do so, then you need to change you approach. You could have operator += return an index to the inserted function, and then you can change operator -= to take that index and remove that element. see eerorika's answer for a suggestion on how to return iterators to the functions.

like image 198
NathanOliver Avatar answered Oct 14 '22 18:10

NathanOliver


Is this possible in C++?

Not like this. Function wrappers cannot be compared for equality. This is a limitation in their design.

One option is to use function pointers. They can be compared for equality. But then you cannot use stateful function objects. NathanOliver shows an example of this.

Another alternative design would be to use a std::list as the container, and when ever you register a function, return iterator to it. Then, instead of erasing by passing the function, you can pass the iterator to be erased.

like image 22
eerorika Avatar answered Oct 14 '22 16:10

eerorika