tr1::mem_fn و tr1::مأزق:على const-صحة الحمولة الزائدة
-
10-07-2019 - |
سؤال
ما هو الخطأ في ما يلي مقتطف ?
#include <tr1/functional>
#include <functional>
#include <iostream>
using namespace std::tr1::placeholders;
struct abc
{
typedef void result_type;
void hello(int)
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
void hello(int) const
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
abc()
{}
};
int
main(int argc, char *argv[])
{
const abc x;
int a = 1;
std::tr1::bind(&abc::hello, x , _1)(a);
return 0;
}
محاولة تجميع مع g++-4.3 ، يبدو أن السيرة الذاتية-تصفيات طاقتها وظائف تخلط كل tr1::mem_fn<>
و tr1::bind<>
ويخرج الخطأ التالية:
no matching function for call to ‘bind(<unresolved overloaded function type>,...
بدلا المقتطف التالي برمجيا ولكن يبدو أن كسر const-صحة:
struct abc
{
typedef void result_type;
void operator()(int)
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
void operator()(int) const
{ std::cout << __PRETTY_FUNCTION__ << std::endl; }
abc()
{}
};
...
const abc x;
int a = 1;
std::tr1::bind( x , _1)(a);
أي فكرة ؟
المحلول
البحث يتم في وقت constness من this
ليست معروفة.عليك أن تعطي تلميحا عن طريق الصب.جرب هذا:
typedef void (abc::*fptr)(int) const; // or remove const
std::tr1::bind((fptr)&abc::hello, x , _1)(a);
قد تلاحظ أيضا هنا أن إزالة const
لا يزال يعمل.هذا هو لأنه يجب أن يمر x من قبل مؤشر (لأن الحجة الأولى إلى C++ الأعضاء الدالة الضمنية this
المعلمة هو دائما مؤشر).جرب هذا بدلا من ذلك:
typedef void (abc::*fptr)(int) const; // won't compile without const (good!)
std::tr1::bind((fptr)&abc::hello, &x , _1)(a);
كما اكتشفت أثناء ضمن التعليقات أدناه ، إذا قمت بحذف &
وأنت أصلا لم لتكون عابرة x من حيث القيمة, التي هي عادة ليست ما تريد (على الرغم من أنه يجعل عملي يذكر الفرق في المثال).هذا يبدو في الواقع مثل مؤسفة شرك عن bind
.
نصائح أخرى
هذا السؤال تمت الإجابة, ولكن أجد أفضل طريقة لتحديد الزائد مع ربط ذلك هو تحديد ذلك على القالب:
std::tr1::bind<void(foo::*)(int)>(&foo::bar);
هذا الأسلوب هو مجرد صريحة ، ولكن أقصر من الصب (مع static_cast
على أي حال.لكنه أنظف من ج-cast, وهو نفس الطول.
كما اقترح جون مشاكل نشأت في تلك المقتطفات التالية:
- عند تمرير الأعضاء-وظيفة-المؤشر من الضروري تحديد التوقيع (إذا طاقتها)
bind()
يتم تمرير الحجج من حيث القيمة.
أول حل المشكلة قبل الصب الأعضاء مؤشر وظيفة توفير ربط:
std::tr1::bind(static_cast< void(abc::*)(int) const >(&abc::hello), x, _1)(a);
الثانية يمكن حلها عن طريق تمرير للاستدعاء كائن من العنوان (كما اقترح جون) ، أو عن طريق TR1 reference_wrapper<>
-- وإلا فإنه سيتم تمريرها حسب القيمة ، مما يجعل const-صحة كسر هلوسة.
نظرا x للاستدعاء وجوه:
std::tr1::bind( std::tr1::ref(x) , _1)(a);
bind()
إلى الأمام a
السليم operator()
وفقا x constness.