Search code examples
c++lambdafunctional-interface

Cast lambda expression to class object whose constructor accept that lambda (Brief lambda)


I am figuring out a way to program a kinda of FunctionalInterface - Java's similar ones - in C++ (although it already provides these features).

I am practicing with Predicate for the moment. Actually I have already done it:

namespace _utils{

    namespace _functional{

        template <typename T>
        class Predicate: public FunctionalI{
            protected:
                std::function<bool(T)> predicate;

            public:
                Predicate(std::function<bool(T)> predicate){
                    this->predicate = predicate;
                }

                inline bool test(T t){
                    return this->predicate(t);
                }
        };
    }
}

And this is main.cpp:

bool foo(_functional::Predicate<int> predicate){
    return predicate.test(2);
}

int main(){
    _functional::Predicate<int> tmp = _functional::Predicate<int>([] (int x) ->  bool{ return x == 2; });

    std::cout << foo(tmp);

    return 0;
}

Now, of course it works!

My question is about how could I make a brief of that lambda expression? I mean, is there any way to pass "directly" the lambda expression (without give it to the Predicate constructor) and then let it construct the Predicate object with right that lambda expression.

I have taken a look at using aliasing and even at functor with operator(), but they did not helped me (maybe I have not been able to do it)

An example of main.cpp which I wish to reach:

bool foo(_functional::Predicate<int> predicate){
    return predicate.test(2);
}

int main(){
    // To much stuff to write
    //std::cout<<foo(_functional::Predicate<int>( [] (int x) -> bool{ return x == 2; } ));

    //What I whish to reach
    foo([] (int x) -> bool{return x == 2;} );

    return 0;
}

Another question to make a brief of lambda expr is: is there a way to make implicit the return type of lambda and even the keyword return?


Solution

  • The problem with foo( [] (int x) -> bool{return x == 2;} ); is that it tries to perform two implicit conversions (lambda to std::function and std::function to Predicate). C++ doesn't allow you to do that. Instead, you can state explicitly that you are initialising Predicate by adding braces:

    foo( { [] (int x) -> bool{return x == 2;} } );
    //   ^ initialise Predicate object        ^
    

    Or create a template constructor as suggested in comments:

    class Predicate : public FunctionalI {
    protected:
        std::function<bool(T)> predicate;
    
    public:
        template <typename PredType>
        Predicate(PredType predicate) : predicate{ std::move(predicate) }
        {
            // use member init list instead of reassigning object in constructor
        }
        // ...
    };