C ++ distinguishes Lambdas from function pointers inside a vector

I am writing a small class of event manager, where I store some pointers to functions inside the vector. I use it std::function<void(int)>as a vector type, I tested the insertion of lambdas and normal functions inside it, and it works:

void t(int p){
  /*things*/
}
[...]
event.bind([](int p){/*things*/});
event.bind(t);

Now (at some point I need to remove lambdas, but not functions), my question is:

Can lambda be distinguished from functions? If so, how?

EDIT:
As I clarified my doubts, this question becomes exactly what the title says

+4
source share
4 answers

: . , . .


, , std::function::target_type. type_info , function. type_info name(), . , , . .

-, . , clang , gcc throws {lambda...#d}. , - :

bool is_identifier(std::string const& id) {
    return id == "(anonymous namespace)" ||
        (std::all_of(id.begin(), id.end(),
        [](char c){
            return isdigit(c) || isalpha(c) || c == '_';
        }) && !isdigit(id[0]));
}

bool is_lambda(const std::type_info& info)
{
    std::unique_ptr<char, decltype(&std::free)> own {
        abi::__cxa_demangle(info.name(), nullptr, nullptr, nullptr),
        std::free
    };

    std::string name = own ? own.get() : info.name();

    // drop leading namespaces... if they are valid namespace names
    std::size_t idx;
    while ((idx = name.find("::")) != std::string::npos) {
        if (!is_identifier(name.substr(0, idx))) {
            return false;
        }
        else {
            name = name.substr(idx+2);
        }
    }

#if defined(__clang__)
    return name[0] == '$';
#elif defined(__GNUC__)
    return name.find("{lambda") == 0;
#else
    // I dunno?
    return false;
#endif
}

- :

void foo(int ) { }
void bar(int ) { }
long quux(long x) { return x; }

int main()
{
    std::vector<std::function<void(int)>> v;

    v.push_back(foo);
    v.push_back(bar);
    v.push_back(quux);
    v.push_back([](int i) { std::cout << i << '\n';});

    std::cout << v.size() << std::endl; // prints 4

    v.erase(
        std::remove_if(
            v.begin(),
            v.end(),
            [](std::function<void(int)> const& f){
                return is_lambda(f.target_type());
            }),
        v.end()
        );

    std::cout << v.size() << std::endl; // prints 3
}
+4

, .

A std::function<void(int)> , r int. .

- . .

, std::function<void(int)> , , - , std::function . " ".

, , , , - , ( ) , .

( , std::function<void(int)> void(*)(int)), . : -, ( , , , , ), -, , std::function, ( void* std::function).

+3

.. , , . , .

std:: function:: target, , , , :

void func1(int) {}
void func2(double) {}

int main()
{

    std::vector<std::function<void(int)>> events;

    events.push_back(func1);
    events.push_back([](int){});
    events.push_back(func2);

    for(auto& e: events)
    {
        if(e.target<void(*)(int)>())
            std::cout << "funcion int" << '\n';
        else if(e.target<void(*)(double)>())
            std::cout << "funcion double" << '\n';
        else
            std::cout << "must be lambda" << '\n';
    }
}

, std:: function:: target , .

:

void func(int) {}

int main()
{

    std::function<void(int)> f = func;

    if(f.target<void(*)(int)>())
        std::cout << "not a lambda" << '\n';
}
+2

Whether it's a function pointer or a lambda, it ends as std::function<void(int)>in vector. Then it std::function<void(int)>is responsible for managing the function pointer or lambda, not yours. This means that you simply remove std::function<void(int)>from vector. The destructor std::function<void(int)>knows how everything is right. In your case, this will not do anything with function pointers and calling the lambda destructor. std::function<void(int)>allows you to handle different things in a beautiful and consistent way. Do not abuse it.

+2
source

Source: https://habr.com/ru/post/1609830/


All Articles