Home > OS >  Initialise a lambda function to be passed as a predicate to std::find_if in C
Initialise a lambda function to be passed as a predicate to std::find_if in C

Time:03-29

I'm trying to initialise a lambda function and then passing as a predicate to std::find_if but receiving the following compiler error. "expression cannot be used as a function".

So how do you first initialise a lambda as a type auto variable and pass it in as a predicate function to an algorithm like std::find_if?

#include <iostream>
#include <vector>
#include <algorithm>
    
    
int main()
{
    std::vector<std::string> vec ={"this", "is", "a", "test", "to",
                                    "see","if", "this", "works", "to", "this", "if"};
    
    auto elimDups_lambda
        {
            [&vec]()
            {
                std::sort(vec.begin(), vec.end());
                vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
                return vec;
            }
        };
    
    for(auto& iter_vec:elimDups_lambda())
            std::cout<<iter_vec<<std::endl;
    
    
    auto lambda_size
        {
            [&vec](size_t x)
            {
                for(auto& iter_vec:vec)
                {
                    if(iter_vec.size()==x)
                        return true;
                    else if(iter_vec >*vec.end())
                        return false;
                }
            }
        };
    
    
     size_t string_size =0;
     std::cin>>string_size;
    
     std::vector<std::string>::iterator find_word =
     std::find_if(vec.begin(), vec.end(), lambda_size(string_size));
    
     std::cout<<*find_word<<std::endl;
        
     return 0;
}

Thank you.

CodePudding user response:

In order to define a variable holding a lambda, you can use syntax similar to this:

auto lambda_var = 
    [&vec]()
    {
        std::sort(vec.begin(), vec.end());
        vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
        return vec;
    };

To use it when calling std::find_if, pass lambda_var (or the name of the variable holding the lambda that you need), as a 3rd parameter to std::find_if

in your code elimDups_lambda and lambda_size are not properly defined to be variables holding lambdas (if this is indeed what you wanted to achieve).

CodePudding user response:

With the expression

lambda_size(string_size)

you call the lambda function, and then the returned bool result will be used as the predicate for std::find_if.

This will of course not work very well.

You can solve this in two ways:

  1. Capture string_size in the lambda; Or

  2. Make the lambda return another lambda for the size check:

    auto lambda_size = [&vec](size_t size)
    {
        return [size](std::string const& word)
        {
            return word.length() == size;
        }
    }
    

Also note how I have changed the logic in the lambda for the comparisons. Your comparison could mean that you dereference the end() iterator for the vector, which isn't allowed. And also that there's a path where the lambda doesn't actually return anything.

Both those problems inside the lambda would lead to undefined behavior.

  • Related