سؤال

أود الاتصال بأعضاء من خلال Lambda :: Bind. لسوء الحظ ، لدي عضوين يحملان نفس الاسم ولكن أنواع الإرجاع المختلفة. هل هناك طريقة لمساعدة Lambda :: ربط استنتاج نوع الإرجاع الصحيح لمكالمة وظيفة العضو؟ (BIND يعمل بشكل جيد مع خصم نوع الإرجاع الصريح)

#include <vector>
#include <iostream>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace std;
using namespace boost;

struct A
{
  A (const string & name) : m_name(name) {}

  string &        name ()         { return m_name; }
  const string &  name () const   { return m_name; }

  string m_name;
};

vector<A> av;

int main () 
{
  av.push_back (A ("some name"));

  // compiles fine
  find_if(av.begin(), av.end(), bind<const string &>(&A::name, _1) == "some name");

  // error: call of overloaded 'bind(<unresolved overloaded function type>, const boost::lambda::lambda_functor<boost::lambda::placeholder<1> >&)' is ambiguous
  find_if(av.begin(), av.end(), lambda::bind(&A::name, lambda::_1) == "some name");

  return 0;
}
هل كانت مفيدة؟

المحلول

أنواع العائد المختلفة هي رنجة حمراء. المشكلة هي مع زيادة التحميل للطريقة (أي سيكون لديك نفس المشكلة بغض النظر عن أنواع العائد النسبية). تم توثيق هذه المشكلة هنا و هنا, ، واستخدام النموذج المحدد نوع الإرجاع ليس الحل الموصى به (ستعمل معظم الوقت ، باستثناء نسخة من MSVC).

تكمن المشكلة في أن أخذ عنوان وظيفة العضو المحملة (إما أن يكون محملاً بشكل زائد أو معلمة محملة) غامضة ، لذلك يلزم بعض المعلومات الإضافية.

يتمثل الحل في إلقاء مؤشر الوظيفة ، والذي يتيح للمترجم معرفة بالضبط أي من الوظائف المحملة التي تريدها ، وأكثر أنظف طريقة للقيام بذلك هي أن تُنص على أنواع مؤشرات الوظائف ، وإلا فإن الخطوط تصبح سيئة بعض الشيء. إليك مثالًا على الكود الخاص بك (تجميع نظيفة GCC 4.3.4):

#include <vector>
#include <iostream>
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace std;
using namespace boost;

struct A
{
  A (const string & name) : m_name(name) {}

  string &        name ()         { return m_name; }
  const string &  name () const   { return m_name; }

  string m_name;
};

vector<A> av;

//function pointer for non-const version
typedef string& (A::*NameFuncType)(void);

//function pointer for const version
typedef const string& (A::*NameConstFuncType)(void) const;

int main () 
{
  av.push_back (A ("some name"));

  //'correct' way to call const version w/ boost::bind
  find_if(av.begin(), av.end(), 
    bind(static_cast<NameConstFuncType>(&A::name), _1) == "some name"
  );

  //call for non-const version w/ boost::lambda::bind
  find_if(av.begin(), av.end(), 
     lambda::bind(static_cast<NameFuncType>(&A::name), lambda::_1) == "some name"
  );

  return 0;
}

نصائح أخرى

للوثائق

"يمكن إعطاء نوع الإرجاع لـ Lambda functor الذي تم إنشاؤه بواسطة تعبير Bind كمعلمة قالب محددة بشكل صريح ، كما في المثال التالي:

ربط (الوظيفة الهدف ، قائمة التوصيل) "

لذلك فقط افعل نفس الشيء الذي فعلته مع Boost: Bind.

  find_if(av.begin(), av.end(), lambda::bind<const string &>(&A::name, lambda::_1) == "some name");

PS لم يتم اختباره

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