سؤال

هل هناك أي طريقة يمكنك الجمع بين المسند؟

دعنا نقول أن لدي شيء مثل هذا:

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" أو السلسلة الأولى التي لا تبدأ ب "-". ومع ذلك، فإن هذا يعطيني خطأ (ثنائي "||" غير محدد).

هل هناك أي طريقة للقيام بذلك؟

هل كانت مفيدة؟

المحلول

يمكنني أن أوصي BOOST.LAMBDA في الجمع بين كائنات الوظائف لمثل هذه المهام. على الرغم من أنها ذات الوزن الثقيل قليلا لمثل هذه المشكلة البسيطة. فيتعديل) انظر مجتمع Wiki الإجابة بدأت Xhantt للحصول على مثال جيد باستخدام STL.

(قديم، مهملة، إجابة) يمكنك كتابة الأداة المساعدة الخاصة بك لهذا، مماثلة:

// 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(...)) ...

نصائح أخرى

حسنا لديك STD :: logical_or. و STD :: COMPOSE2. التي يمكن أن تفعل الوظيفة

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

لكنني أعتقد أن التعزيز :: Lambda و / أو Phoenix أكثر قابلية للقراءة في النهاية، وهنا حلاي الموصى به.

يجب أن تذهب الاعتمادات إلى وثائق SGI.

إذا كنت ترغب في إنشاء المسندات، فإن أجمل طريقة لكتابةها ربما تستخدم Boost Lambda أو Boost Phoenix:

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

بالنسبة إلى طريقة فينيكس واحدة من الاحتمالات هي استخدام وظائف فينيكس كسول، ويمكن أن يبدو الحل مشابه للواحد أدناه:

// 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 أو زيادة XPESTIVE). إذا كنت ترغب في التعامل مع خيارات سطر الأوامر، فاستخدم خيارات برنامج Boost.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top