【问题标题】:how to create function that returns a functor with the same signature as the function?如何创建返回与函数具有相同签名的函子的函数?
【发布时间】:2013-06-23 11:53:27
【问题描述】:

是否有可能在 C++ 中创建返回具有与函数相同签名的函子的函数?

基本上,如何使decltype(foo) foo();合法化。

或使用仿函数:function<function<function<...(void)>(void)>(void)>

我想将它用于状态机,其中每个状态都是一个函数,它将函子返回到对象的下一个状态。我现在已经使用枚举实现了它,但我觉得一定有更好的方法:

#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();
}

还有:有没有更简洁的方式来表达这个问题?

【问题讨论】:

  • 你为什么用 C++ 而不是 VHDL 编写状态机代码?
  • 因为我说的是数学抽象,而不是实际的机器。
  • 这取决于您所说的“返回”是什么意思。函子在某种程度上表现得像函子,所以编译器在返回任何东西之前仍然会评估函子的值,所以你最终会得到递归。
  • 我的意思是只返回函子而不评估它。 (作为函数指针)
  • 所以你试图从state返回函数f

标签: c++ recursion c++11 functor state-machine


【解决方案1】:

您可以通过将函数包装在结构中来打破类型递归:

#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;
}

更新:在 Yakk(“让它更通用”)和 Luc Danton(“经典GOTW”)的 cmets 之后,我在下面添加了一个更通用的 C++11 版本,它基于 GOTW 版本。

/// 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;
}

【讨论】:

  • operator() 会大大改善这一点。
  • 我可能会受到诱惑的唯一其他更改是将 std::string 设置为 template arg。哦,在您的operator() 中完美转发。
  • 是的,参数甚至应该是一个参数包,但我只是想展示一个状态函数有参数的例子。我有点担心进一步的概括会分散重点(另外:我仍然是一名 C++98 程序员)。
猜你喜欢
  • 2015-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2019-10-18
相关资源
最近更新 更多