Должно быть &A::Func1, хотя MSVC++6.0 этого и не требует.
WC>Под родным stl одна ошибка, под stlport другая. Интересуют соображения по обоих случаях
После исправлений, указанных выше, под STLport будет работать. С родной STL дело чуть хуже. В заголовке <functional> не хватает версий std::mem_fun... для константных функций-членов.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
WC>Под родным stl одна ошибка, под stlport другая. Интересуют соображения по обоих случаях
В стандартном варианте класс mem_fun_ref_t объявлен так:
template<class _R, class _Ty, class _A>
class mem_fun1_ref_t : public binary_function<_Ty * , _A, _R>
при этом получается, что mem_fun1_ref_t::first_argument_type есть A*!!! (A — имя твоего класса), а bind2nd<Pred> использует Pred::first_argument_type в operator(), и в твоем случае этот тип должен соответствовать A, что при имеющемся объявлении mem_fun1_ref_t не так.
Я немного подправил mem_fun1_ref, и вот что получилось в результате (нужные места выделены жирным шрифтом):
template<class _R, class _Ty, class _A>
class mem_fun1_ref_t_corrected : public binary_function<_Ty , _A, _R> {
public:
explicit mem_fun1_ref_t_corrected(_R (_Ty::*_Pm)(_A))
: _Ptr(_Pm) {}
_R operator()(const_Ty& _X, _A _Arg) const
{return ((_X.*_Ptr)(_Arg)); }
private:
_R (_Ty::*_Ptr)(_A);
};
template<class _R, class _Ty, class _A> inline
mem_fun1_ref_t_corrected<_R, _Ty, _A> mem_fun1_ref_corrected(_R (_Ty::*_Pm)(_A))
{return (mem_fun1_ref_t_corrected<_R, _Ty, _A>(_Pm)); }
теперь, если использовать mem_fun1_ref_corrected, все работает как надо...
Но в душу закрадываются сомнения — зачем было объявлять mem_fun1_ref_t именно так?!
В каких-то других местах предполагается, что first_argument_type должен быть указателем?
Хотя в STLPort все объявлено нормально, т.е.
template <class _Ret, class _Tp, class _Arg>
class mem_fun1_ref_t : public binary_function<_Tp,_Arg,_Ret>
Здравствуйте Павел Кузнецов, Вы писали:
ПК>Должно быть &A::Func1, хотя MSVC++6.0 этого и не требует.
ПК>После исправлений, указанных выше, под STLport будет работать.
А вот и нет
Дело не в этом (причину я указал в предыдущем ответе)
Здравствуйте Bell, Вы писали:
ПК>>После исправлений, указанных выше, под STLport будет работать. B>А вот и нет B>Дело не в этом (причину я указал в предыдущем ответе)
Тут вы, батенька, поторопились Вашу mem_fun1_ref_t_corrected следовало назвать mem_fun1_ref_t_broken, т.к. теперь через нее нельзя вызывать неконстантные члены-функции. По стандарту (см. 20.3.8) шаблон mem_fun1_ref_t объявлен так:
template <class S, class T, class A> class mem_fun1_ref_t
: public binary_function<T, A, S> {
public:
explicit mem_fun1_ref_t(S (T::*p)(A));
S operator()(T& p, A x) const;
};
Кроме того, для константных функций-членов есть еще const_mem_fun1_ref_t:
template <class S, class T, class A> class const_mem_fun1_ref_t
: public binary_function<T, A, S> {
public:
explicit const_mem_fun1_ref_t(S (T::*p)(A) const);
S operator()(const T& p, A x) const;
};
Второй шаблон отсутствует в MSVC++6.0.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
выражению _Operation::first_argument_type соответствует _Ty * , а for_each в качестве параметра передает объект типа _Ty
Вот это и есть причина ошибки.
Что касается приведенных Вами определений mem_fun1_ref и const_mem_fun1_ref — то здесь все нормально, но строка
B>Но все равно проблема стандартного STL
Не стандартного, а старого Dinkumware
B> не в отсутствии дополнительного "константного" шаблона, а в определении mem_fun1_ref_t: B>template<class _R, class _Ty, class _A> B>class mem_fun1_ref_t : public binary_function<_Ty * , _A, _R>
И в этом тоже.
B>Что касается приведенных Вами определений mem_fun1_ref и const_mem_fun1_ref — то здесь все нормально, но строка B>for_each(v.begin(),v.end(),bind2nd(mem_fun1_ref( A::Func1 ),10) ); B>все равно не будет компилиться, если A::Func1 не объявлена с модификатором const.
Более того, так как в MSVC++6.0 отсутствуют версии адаптеров для константных функций-членов, при вызове функции mem_fun1_ref(&A::Func1) компилятор выдаст ошибку о том, что не может преобразовать 'int(A::*)(int) const' к типу 'int(A::*)(int)'. На это я и указал в своем первом сообщении (может, чуть более кратко, нежели следовало)
B>Или есть биндер, у которого operator() объявлен так: B>binder2nd::operator()(typename _Operation::first_argument_type& __x) const
Может и есть, но он не входит в стандартную библиотеку C++ и, в любом случае, в нем нет никакой необходимости, т.к. при конкретизации binder2nd<const_mem_fun1_ref_t<R, T, A> >, _Operation::first_argument_type == const T.
Резюме: для того, чтобы приведенный фрагмент кода компилировался MSVC++6.0 на "родной" STL, надо внести (как минимум) два изменения в заголовок <functional>: исправить объявление (как верно заметил Bell)
class mem_fun1_ref_t : public binary_function<_Ty * , _A, _R> на
class mem_fun1_ref_t : public binary_function<_Ty, _A, _R>
добавить реализацию адаптеров для константных функций-членов перед строкой _STD_END
// TEMPLATE CLASS const_mem_fun_ttemplate<class _R, class _Ty>
class const_mem_fun_t : public unary_function<const _Ty *, _R> {
public:
explicit const_mem_fun_t(_R (_Ty::*_Pm)() const)
: _Ptr(_Pm) {}
_R operator()(const _Ty *_P) const
{return ((_P->*_Ptr)()); }
private:
_R (_Ty::*_Ptr)() const;
};
// TEMPLATE FUNCTION mem_funtemplate<class _R, class _Ty> inline
const_mem_fun_t<_R, _Ty> mem_fun(_R (_Ty::*_Pm)() const)
{return (const_mem_fun_t<_R, _Ty>(_Pm)); }
// TEMPLATE CLASS const_mem_fun1_ttemplate<class _R, class _Ty, class _A>
class const_mem_fun1_t : public binary_function<const _Ty *, _A, _R> {
public:
explicit const_mem_fun1_t(_R (_Ty::*_Pm)(_A) const)
: _Ptr(_Pm) {}
_R operator()(const _Ty *_P, _A _Arg) const
{return ((_P->*_Ptr)(_Arg)); }
private:
_R (_Ty::*_Ptr)(_A) const;
};
// TEMPLATE FUNCTION mem_fun1template<class _R, class _Ty, class _A> inline
const_mem_fun1_t<_R, _Ty, _A> mem_fun1(_R (_Ty::*_Pm)(_A) const)
{return (const_mem_fun1_t<_R, _Ty, _A>(_Pm)); }
// TEMPLATE CLASS const_mem_fun_ref_ttemplate<class _R, class _Ty>
class const_mem_fun_ref_t : public unary_function<const _Ty, _R> {
public:
explicit const_mem_fun_ref_t(_R (_Ty::*_Pm)() const)
: _Ptr(_Pm) {}
_R operator()(const _Ty& _X) const
{return ((_X.*_Ptr)()); }
private:
_R (_Ty::*_Ptr)() const;
};
// TEMPLATE FUNCTION mem_fun_reftemplate<class _R, class _Ty> inline
const_mem_fun_ref_t<_R, _Ty> mem_fun_ref(_R (_Ty::*_Pm)() const)
{return (const_mem_fun_ref_t<_R, _Ty>(_Pm)); }
// TEMPLATE CLASS const_mem_fun1_ref_ttemplate<class _R, class _Ty, class _A>
class const_mem_fun1_ref_t : public binary_function<const _Ty, _A, _R> {
public:
explicit const_mem_fun1_ref_t(_R (_Ty::*_Pm)(_A) const)
: _Ptr(_Pm) {}
_R operator()(const _Ty& _X, _A _Arg) const
{return ((_X.*_Ptr)(_Arg)); }
private:
_R (_Ty::*_Ptr)(_A) const;
};
// TEMPLATE FUNCTION mem_fun1_reftemplate<class _R, class _Ty, class _A> inline
const_mem_fun1_ref_t<_R, _Ty, _A> mem_fun1_ref(_R (_Ty::*_Pm)(_A) const)
{return (const_mem_fun1_ref_t<_R, _Ty, _A>(_Pm)); }
что подтверждается полевыми испытаниями
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен