2009-02-13 14 views
7

क्या कोई तरीका है कि आप भविष्यवाणी कर सकते हैं?भविष्यवाणियों का मिश्रण

चलें कहते हैं कि मैं कुछ इस तरह है:

class MatchBeginning : public binary_function<CStdString, CStdString, bool> 
{ public: 
      bool operator()(const CStdString &inputOne, const CStdString &inputTwo) const 
    { return inputOne.substr(0, inputTwo.length()).compare(inputTwo) == 0; } 
}; 

int main(int argc, char* argv[]) 
{ 
    CStdString myString("foo -b ar -t az"); 

    vector<CStdString> tokens; 

    // splits the string every time it encounters a "-" 
    split(myString, tokens, "-", true, true); 

    vector<CStdString>::iterator searchResult = find_if(tokens.begin(), tokens.end(), not1(bind2nd(MatchBeginning(), "-")));   

    return 0; 
} 

यह काम करता है, लेकिन अब मैं कुछ ऐसा करना चाहते हैं:

searchResult = find_if(tokens.begin(), tokens.end(), bind2nd(MatchBeginning(), "-b") || not1(bind2nd(MatchBeginning(), "-"))); 

तो मैं पहली स्ट्रिंग प्राप्त करना चाहते हैं जो "-b" या पहली स्ट्रिंग से शुरू होता है जो "-" से शुरू नहीं होता है। हालांकि, यह मुझे एक त्रुटि देता है (बाइनरी '||' अपरिभाषित)।

क्या ऐसा करने का कोई तरीका है?

उत्तर

5

मैं ऐसे कार्यों के लिए फ़ंक्शन-ऑब्जेक्ट्स को संयोजित करने के लिए boost.lambda की अनुशंसा कर सकता हूं। हालांकि यह इतनी सरल समस्या के लिए थोड़ा हेवीवेट है। (संपादित करें) एसटीएल का उपयोग करके एक अच्छा उदाहरण के लिए xhantt द्वारा शुरू किया गया समुदाय विकी उत्तर देखें।

(पुराने, बहिष्कृत, जवाब) आप इस के लिए अपनी खुद की उपयोगिता, समान लिख सकते हैं:

// here we define the combiner... 
template<class Left, class Right> 
class lazy_or_impl { 
    Left m_left; 
    Right m_right; 
public: 
    lazy_or_impl(Left const& left, Right const& right) : m_left(left), m_right(right) {} 
    typename Left::result_type operator()(typename Left::argument_type const& a) const { 
    return m_left(a) || m_right(a); 
    } 
}; 

// and a helper function which deduces the template arguments 
// (thx to xtofl to point this out) 
template<class Left, class Right> 
lazy_or_impl<Left, Right> lazy_or(Left const& left, Right const& right) { 
    return lazy_or_impl<Left, Right>(left, right); 
} 

और फिर इसे का उपयोग करें: ... lazy_or(bind1st(...), bind1st(...)) ...

+1

आपको संकलन के लिए शायद एक शिम फ़ंक्शन की आवश्यकता होगी: कक्षाओं के लिए कोई टेम्पलेट तर्क अनुमान नहीं है। – xtofl

+0

Thx इसे इंगित करने के लिए, मैंने जवाब संपादित किया, और कुछ अन्य भाग भी तय किया ... – gimpf

4

आप विधेय रचना चाहते हैं, करने के लिए सबसे अच्छा तरीका यह शायद बूस्ट लैम्ब्डा उपयोग कर रहा है लिख सकते हैं या बूस्ट फीनिक्स:

// Lambda way: 
// Needs: 
// #include <boost/lambda/lambda.hpp> 
// #include <boost/lambda/bind.hpp> 
{ 
    using namespace boost::lambda; 
    foo_vec::const_iterator it 
     = std::find_if(
        tokens.begin(), 
        tokens.end(), 
        bind(MatchBeginning(), _1, "-b") || !bind(MatchBeginning(), _1, "-") 
        ); 
} 
// Boost bind way: 
// Needs: 
// #include <boost/bind.hpp> 
{ 
    foo_vec::const_iterator it 
     = std::find_if(
        tokens.begin(), 
        tokens.end(), 
        boost::bind(
           std::logical_or<bool>(), 
           boost::bind(MatchBeginning(), _1, "-b"), 
           !boost::bind(MatchBeginning(), _1, "-") // ! overloaded in bind 
           ) 
        ); 

फीनिक्स रास्ता संभावनाओं में से एक फोनिक्स आलसी कार्यों का उपयोग करने के लिए है के लिए, और समाधान ग ould नीचे एक के समान दिखाई:

// Requires: 
// #include <boost/spirit/include/phoenix_core.hpp> 
// #include <boost/spirit/include/phoenix_function.hpp> 
// #include <boost/spirit/include/phoenix_operator.hpp> 
namespace phx = boost::phoenix; 

struct match_beginning_impl 
{ 
    template <typename Arg1, typename Arg2> 
    struct result 
    { 
     typedef bool type; 
    }; 

    template <typename Arg1, typename Arg2> 
    bool operator()(Arg1 arg1, Arg2 arg2) const 
    { 
     // Do stuff 
    } 
}; 
phx::function<match_beginning_impl> match_beginning; 

using phx::arg_names::arg1; 

foo_vec::const_iterator it 
    = std::find_if(
       tokens.begin(), 
       tokens.end(), 
       match_beginning(arg1, "-b") || !match_beginning(arg1, "-") 
       ); 

हालांकि अपने कार्य को पूरा करने यह शायद विभिन्न उपकरणों को रोजगार के लिए और अधिक समझ में आता है - उदाहरण के लिए: नियमित अभिव्यक्ति (Regex बूस्ट या Xpressive बूस्ट)। यदि आप कमांड लाइन विकल्पों को संभालना चाहते हैं तो बूस्ट प्रोग्राम विकल्प का उपयोग करें।

+0

मेरी इच्छा है कि मैं इस प्रश्न के दो जवाब स्वीकार कर सकता हूं। अंत में मैंने गैर-लाइब्रेरी मार्ग को सबसे दिलचस्प पाया। फिर भी, इन स्निपेट को लिखने के लिए समय देने के लिए धन्यवाद। – drby

5

वैसे आप std::logical_or और std::compose2 कि नौकरी

find_if(tokens.begin(), tokens.end(), 
    compose2(logical_or<bool>(), 
    bind2nd(MatchBeginning(), "-b"), 
    bind2nd(MatchBeginning(), "-") 
) 
); 

कर सकते हैं, लेकिन मुझे लगता है कि बढ़ावा :: लैम्ब्डा और/या फोनिक्स अंत में अधिक पठनीय हैं, और मेरी सिफारिश समाधान कर रहे हैं।

क्रेडिट एसजीआई दस्तावेज पर जाना चाहिए।

+0

मुझे पता था कि मैं स्पष्ट रचना भूल गया हूं। मुझे बस logical_or मिला, और बस इसे याद नहीं किया :-( – gimpf

+0

compose2 के साथ समस्या यह है कि यह वर्तमान C++ मानक का हिस्सा नहीं है। – Anonymous

+0

अच्छा, न तो boost :: lambda और न ही फीनिक्स मानक का हिस्सा हैं, फिर भी। – Ismael

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