"لا يمكن تحويل المعلمة" باستخدام دفعة :: اختبار المتغير
-
13-09-2019 - |
سؤال
أريد إنشاء وظيفة يمكن أن تتخذ أنواعا مختلفة من المحفون الذين يخزنون نفس النوع من الكائن:
الأول هو std::map
تحتوي shared_ptr<Foo>
(typedef-ed كما FooMap
) والآخر هو std::list
التي تحتوي أيضا على shared_ptr<Foo>
(FooList
).
انا فعلا احب اقترح Msalters الحل لسؤال مماثل وحاول تنفيذ boost::variant
المحامي، الذي ستحصل فيه الوظيفة كمعلمات للتكرار من الأول إلى الثاني.
وظيفتي تبدو وكأنها (مبسطة قليلا جدا):
set<Foo> CMyClass::GetUniqueFoos(FooIterator itBegin, FooIterator itEnd)
{
set<Foo> uniques;
for(/**/;
apply_visitor(do_compare(), itBegin, itEnd); // equals "itBegin != itEnd"
apply_visitor(do_increment(), itBegin)) // equals "++itBegin"
{
// Exact mechanism for determining if unique is omitted for clarity
uniques.insert( do_dereference< shared_ptr<Foo> >(), itBegin) );
}
return uniques;
}
يتم تعريف Foo Niterator والزائرين على النحو التالي:
typedef
boost::variant<
FooMap::const_iterator,
FooList::const_iterator>
FooIterator;
struct do_compare : boost::static_visitor<bool>
{
bool operator() (
const FooMap::const_iterator & a,
const FooMap::const_iterator & b) const
{ return a != b; }
bool operator() (
const FooList::const_iterator & a,
const FooList::const_iterator & b) const
{ return a != b; }
};
struct do_increment: boost::static_visitor<void>
{
template<typename T>
void operator()( T& t ) const
{ ++t; }
};
template< typename Reference >
struct do_dereference: boost::static_visitor<Reference>
{
template<typename T>
Reference operator()( const T& t ) const
{ return *t; }
};
حصلت على معظم ما سبق من مرفق هذا البريد. وبعد يستخدم هذا الحل أيضا محولات وسياسات، والتي يبدو أنها أكثر من اللازم قليلا، وفقا لإجابة رسائن الملابس، لذلك لا أرغب في نسخ هذا الرمز ببساطة. خاصة وأنا أفهم جزء منه فقط.
مع الرمز أعلاه، أحصل على خطأ مترجم أعلاه من VS2008 (هذا فقط الأسطر القليلة الأولى من 160 في المجموع، والتي أعتقد أنها أكثر من اللازم للنشر هنا؛ ومع ذلك، سأكون سعيدا بإضافتهم إذا كان شخص ما يريد انظر كل شيء):
1>c:\boost\boost\variant\detail\apply_visitor_binary.hpp(63) :
error C2664: 'bool CMyClass::do_compare::operator ()(
const std::list<_Ty>::_Const_iterator<_Secure_validation> &,
const std::list<_Ty>::_Const_iterator<_Secure_validation> &) const' :
cannot convert parameter 1 from 'T0' to
'const std::list<_Ty>::_Const_iterator<_Secure_validation> &'
1> with
1> [
1> _Ty=shared_ptr<Foo>,
1> _Secure_validation=true
1> ]
1> Reason: cannot convert from 'T0' to 'const std::list<_Ty>::_Const_iterator<_Secure_validation>'
1> with
1> [
1> _Ty=shared_ptr<Foo>,
1> _Secure_validation=true
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1> c:\boost\boost\variant\variant.hpp(806) : see reference to function template instantiation 'bool boost::detail::variant::apply_visitor_binary_invoke<Visitor,Value1>::operator ()<T>(Value2 &)' being compiled
1> with
1> [
1> Visitor=const CMyClass::do_compare,
1> Value1=T0,
1> T=T1,
1> Value2=T1
1> ]
[...]
ما الخطأ الذي افعله؟
المحلول
أظن أنك في عداد المفقودين حالات على do_compare static_visitor. Remeber، قد يكون المتغيرات أي شيء، لذلك تحتاج إلى جميع المجموعات الممكنة، مثل مقارنة أحمق :: const_iterator إلى Foomap :: const_iterator. إنه يشكو لأن المترجم يحاول العثور على بعض مباراة لهذه الحالة، ولا يمكن تحويل Foomap :: Const_iterator إلى FOOD_AT_ATITATOR.
ضربها:
struct do_compare : boost::static_visitor<bool>
{
bool operator() (
const FooMap::const_iterator & a,
const FooMap::const_iterator & b) const
{ return a != b; }
bool operator() (
const FooList::const_iterator & a,
const FooList::const_iterator & b) const
{ return a != b; }
bool operator() (
const FooMap::const_iterator & a,
const FooList::const_iterator & b) const
{ return false; }
bool operator() (
const FooList::const_iterator & a,
const FooMap::const_iterator & b) const
{ return false; }
};
إليك إصدار مع القوالب:
template <typename A, typename B>
bool operator() (
const A & a,
const B & b) const
{ return false; }
template <typename A>
bool operator() (
const A & a,
const A & b) const
{ return a != b; }
إنها تجميعها على COMEAU، لكنني لست 100٪ ستعمل، لذلك مطلوب بعض الاختبارات. بخلاف Cleaner، رمز أكثر تنوعا، لا ينبغي أن يكون لها أي تأثير، طالما أنه يعمل.