2013-06-23 12 views
7

क्या सी ++ में ऐसा फ़ंक्शन बनाने के लिए संभव है जो फ़ंक्शन के समान हस्ताक्षर वाले फ़ंक्शन को लौटाता हो?फ़ंक्शन कैसे बनाएं जो फ़ंक्शन के समान हस्ताक्षर वाले फ़ंक्शन को लौटाता है?

मूल रूप से, decltype(foo) foo(); को वैध कैसे करें।

या functors के साथ: function<function<function<...(void)>(void)>(void)>

मैं जहां हर राज्य में एक समारोह है कि वस्तु के अगले राज्य के लिए एक functor देता है एक राज्य मशीन के लिए इसका उपयोग करना चाहते हैं। मैं अब enums का उपयोग कर इसे क्रियान्वित किया है, लेकिन मैं की तरह वहाँ एक बेहतर तरीका होना चाहिए लग रहा है:

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

भी: वहाँ सवाल वाक्यांश के लिए एक कम भद्दा तरीका है?

+0

आप वीएचडीएल के बजाय सी ++ में राज्य मशीन कोड क्यों लिख रहे हैं? –

+3

क्योंकि मैं गणितीय अमूर्तता के बारे में बात कर रहा हूं और वास्तविक मशीन के बारे में नहीं। –

+0

वैसे यह निर्भर करता है कि "वापसी" से आपका क्या मतलब है। फंक्शंस एक तरह से मज़ेदार व्यवहार करते हैं, इसलिए संकलक अभी भी कुछ भी लौटने से पहले मज़ेदार के मूल्य का मूल्यांकन करेगा ताकि आप रिकर्सन के साथ समाप्त हो जाएंगे। –

उत्तर

7

आप एक 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; 
} 

अद्यतन: Yakk द्वारा टिप्पणियों के बाद ('बनाने के लिए इसे और अधिक सामान्य') और ल्यूक डेंटन ("क्लासिक GOTW") मैं मैं नीचे एक अधिक सामान्य सी ++ 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; 
} 
+0

यह 'ऑपरेटर() 'द्वारा काफी सुधार किया जाएगा। – Yakk

+0

@ यक, आप सही हैं। ऑपरेटर जोड़ा। _And_ कॉन्स जोड़ने के लिए धन्यवाद ... – dhavenith

+0

एकमात्र अन्य परिवर्तन जो मुझे लगाया जा सकता है वह 'std :: string'' टेम्पलेट' तर्क बना रहा है। ओह और आपके 'ऑपरेटर() 'में सही अग्रेषण। – Yakk

संबंधित मुद्दे