Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to create function that returns a functor with the same signature as the function?

Is it possible in c++ to create function that returns a functor with the same signature as the function?

basicly, how to legalise decltype(foo) foo();.

or with functors:function<function<function<...(void)>(void)>(void)>

I'd like to use this for a state-machine where every state is a function that returns a functor to the next state of the object. I've now implemented it using enums, but I feel like there must be a better way:

#include <iostream>
using namespace std;

enum functionenum{END,FOO,BAR,BAZ};

functionenum foo(){
    cout<<"FOO! > ";
    string s;
    cin>>s;
    if(s=="end") return END;
    if(s=="bar") return BAR;
                 return FOO;
}

functionenum bar(){
    cout<<"BAR! > ";
    string s;
    cin>>s;
    if(s=="end") return END;
    if(s=="baz") return BAZ;
                 return BAR;
}

functionenum baz(){
    cout<<"BAZ! > ";
    string s;
    cin>>s;
    if(s=="end") return END;
    if(s=="bar") return BAR;
    if(s=="foo") return FOO;
                 return BAZ;
}

void state(){
    auto f=foo;
    while(true){
        switch (f()){
        case FOO: f=foo; break;
        case BAR: f=bar; break;
        case BAZ: f=baz; break;
        case END: return;
        };
    };
}

int main(){
    state();
}

also: is there a less clunky way to phrase the question?

like image 456
Douwe van Gijn Avatar asked Jun 23 '13 11:06

Douwe van Gijn


People also ask

How do you make a functor?

Functors are called using the same old function call syntax. To create a functor, we create a object that overloads the operator(). The line, MyFunctor(10); Is same as MyFunctor. operator()(10);

What is the difference between a function and a functor?

A function assigns to every element of a set X an element of a set Y. A functor assigns to every object of a category C an object of a category D and also assigns to every morphism in C a morphism in D in a way compatible with sources, targets, and composition.

What is a function object functor )? Demonstrate with an example?

A function object, or functor, is any type that implements operator(). This operator is referred to as the call operator or sometimes the application operator. The C++ Standard Library uses function objects primarily as sorting criteria for containers and in algorithms.

Is a lambda a functor?

Summary and References. We have seen that lambda is just a convenient way to write a functor, therefore we should always think about it as a functor when coding in C++. We should use lambdas where we can improve the readability of and simplify our code such as when writing callback functions.


1 Answers

You could break the type-recursion by wrapping the function in a struct:

#include <string>

struct state
{
    typedef state (*state_func)( const std::string &);
    state( state_func f): function(f){} //not explicit, for notational convenience
    state operator()( const std::string&arg) const
    {
        return function( arg);
    }
private:
    state_func function;

};

state f( const std::string &);
state g( const std::string &)
{
    return &f;
}
state f( const std::string &)
{
    return &g;
}

int main()
{
    state s(&f);
    s = s( "hello");
    return 0;
}

UPDATE: after comments by Yakk ('make it more generic') and Luc Danton ("Classic GOTW") I'm adding a more generic C++11 version below, that is based on the GOTW version.

/// Type that wraps functions that return functions with the same signature.
template<typename... Arguments>
struct SelfReturningFunction
{
    typedef SelfReturningFunction (*FunctionPointer)( Arguments...);
    SelfReturningFunction( FunctionPointer f): function(f){} 
    operator FunctionPointer() const
    {
        return function;
    }
private:
    FunctionPointer function;
};

// example usage
#include <string>

using state = SelfReturningFunction<const std::string&>;

state f( const std::string &);
state g( const std::string &)
{
    return &f;
}
state f( const std::string &)
{
    return &g;
}
state dead_end( const std::string &)
{
    return &dead_end;
}

int main()
{
    state s{&f};
    s = s( "hello");
    return 0;
}
like image 68
dhavenith Avatar answered Sep 29 '22 20:09

dhavenith