Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lambda parameter with optional return value

I'm trying to write a function like std::for_each, that in addition to the normal usage, can also take a std::function<bool (param)>. A false return value means that I want to break out of the loop. The code below is what I've gotten so far.

The second call to a.visit([&](int) -> void) does not compile when evaluating !visitor(i). Is it possible to make this work or am I barking up the wrong tree?

I'm using MSVC 2010 but want the code to be generally C++11 compatible.

#include <list>
#include <string>
#include <iostream>

struct A 
{
    std::list<int> _lst;

    template<typename _F>
    void visit(_F visitor) 
    {
        for(std::list<int>::const_iterator it = _lst.begin(), end = _lst.end() ; it != end ; it++) {
            int i = *it;
            if (std::is_void<decltype(visitor(i))>::value) {
                visitor(i);
            } else {
               if (!visitor(i)) { // <----- error C2171: '!' : illegal on operands of type 'void'
                   break;
               }
            }
        }
    }

};

int main(int argc, char* argv[])
{
    A a;
    // populate a
    for (int i = 0 ; i < 10 ; i++) { 
        a._lst.push_back(i); 
    }

    a.visit([](int i) -> bool {
        std::cout << i << std::endl;
        return i < 5;
    });

    a.visit([](int i) {
        std::cout << i << std::endl;
    });
}
like image 333
kylewm Avatar asked Oct 01 '13 01:10

kylewm


People also ask

Can lambda have a return type?

The return type for a lambda is specified using a C++ feature named 'trailing return type'. This specification is optional. Without the trailing return type, the return type of the underlying function is effectively 'auto', and it is deduced from the type of the expressions in the body's return statements.

Can Python lambda have default arguments?

A Python lambda function behaves like a normal function in regard to arguments. Therefore, a lambda parameter can be initialized with a default value: the parameter n takes the outer n as a default value.

Can lambda return value?

The lambda function can take many arguments but can return only one expression.

Which is not optional in lambda functions?

In Kotlin, the lambda expression contains optional part except code_body.


1 Answers

Here's how I would implement for_almost_each; I'm using namespace std plus type aliases for readability purposes.

#include <algorithm>
#include <iterator>
#include <functional>

using namespace std;

template<class Iter, class Func>
Iter
for_almost_each_impl(Iter begin, Iter end, Func func, std::true_type)
{
    for (auto i = begin; i!=end; ++i)
        if (!func(*i))
            return i;
    return end;
}

template<class Iter, class Func>
Iter
for_almost_each_impl(Iter begin, Iter end, Func func, std::false_type)
{
    for_each(begin, end, func);
    return end;
}


template<class Iter, class Func>
Iter for_almost_each(Iter begin, Iter end, Func func)
{
    using Val = typename iterator_traits<Iter>::value_type;
    using Res = typename result_of<Func(Val)>::type;
    return for_almost_each_impl(begin, end,
                                func,
                                is_convertible<Res, bool>{} );
}

I used is_convertible, as it seems to make more sense than is_same.

like image 160
DanielKO Avatar answered Sep 24 '22 05:09

DanielKO