2013-06-23 31 views
7

Có thể trong C++ để tạo hàm trả về một hàm functor có cùng chữ ký với hàm không?cách tạo hàm trả về hàm functor có cùng chữ ký với hàm?

cơ bản, cách hợp pháp hóa decltype(foo) foo();.

hoặc với functors: function<function<function<...(void)>(void)>(void)>

Tôi muốn sử dụng này cho một nhà máy mà mỗi tiểu bang là một hàm trả về một functor sang trạng thái tiếp theo của đối tượng. Bây giờ tôi đã thực hiện nó bằng cách sử enums, nhưng tôi cảm thấy như có phải là một cách tốt hơn:

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

thêm: là có một cách ít clunky với cụm từ các câu hỏi?

+0

Tại sao bạn viết mã máy nhà nước bằng C++ thay vì VHDL? –

+3

Bởi vì tôi đang nói về trừu tượng toán học chứ không phải về một cỗ máy thực tế. –

+0

Vâng nó phụ thuộc vào những gì bạn có nghĩa là "trở lại". Functors hoạt động giống như các chức năng trong một cách, do đó trình biên dịch sẽ vẫn đánh giá giá trị của hàm functor trước khi trả về bất cứ điều gì, do đó bạn sẽ kết thúc với đệ quy. –

Trả lời

7

Bạn có thể phá vỡ các kiểu đệ quy bằng cách gói các chức năng trong một cấu trúc:

#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: sau lời bình luận của Yakk ('làm cho nó chung chung hơn') và Luc Danton ("Classic GOTW") Tôi đang thêm một phiên bản C++ 11 chung hơn bên dưới, dựa trên phiên bản 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; 
} 
+0

Điều này sẽ được cải thiện nhiều hơn bởi toán tử '()'. – Yakk

+0

@Yakk, bạn nói đúng. đã thêm toán tử. _And_ cảm ơn cho việc thêm các const ... – dhavenith

+0

Chỉ những thay đổi khác mà tôi có thể bị cám dỗ là làm cho 'std :: string' thành' template' arg. Oh và chuyển tiếp hoàn hảo trong toán tử 'của bạn()'. – Yakk

Các vấn đề liên quan