Boost Lambda :: Bind Return Type Selection
-
02-10-2019 - |
سؤال
أود الاتصال بأعضاء من خلال 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 لم يتم اختباره