/*!
\page	cpp_util_2__unary_method	cpp_util_2: Обертки для вызова унарных методов объектов

\section	cpp_util_2__unary_method__intro	Введение

	Необходимость в классах cpp_util_2::unary_method_t
	(cpp_util_2::const_unary_method_t) возникла при очередном использовании
	функции std::for_each. Был список std::string и был класс у которого
	нужно было вызвать метод для каждого из элементов список.
	Простое решение:
\code
class	actor_t
{
	public :
		void
		some_method( const std::string & o );
		...
};

void
initialize_actor
	( actor_t & actor,
	  const std::list< std::string > & l )
{
	for( std::list< std::string >::const_iterator
		it = l.begin(), it_end = l.end();
		it != it_end;
		++it )
	{
		actor.some_method( *it );
	}
}
\endcode
	хотелось заменить на использование std::for_each:
\code
void
initialize_actor
	( actor_t & actor,
	  const std::list< std::string > & l )
{
	std::for_each( l.begin(), l.end(), ... );
}
\endcode
	С помощью STL это можно было бы сделать, например, так:
\code
void
initialize_actor
	( actor_t & actor,
	  const std::list< std::string > & l )
{
	std::for_each
		( l.begin(),
		  l.end(),
		  std::bind1st
			( std::mem_fun( &actor_t::some_method ),
			  &actor ) );
}
\endcode
	Но здесь возникают сразу две проблемы:
	- ни один из имеющихся в моем распоряжении компиляторов
	не мог скомпилировать выражение
	<tt>std::bind1st( std::mem_fun( &actor_t::some_method ), &actor )</tt>,
	т.к. из-за типа параметра метода <tt>actor_t::some_method</tt>
	компилятор пытался построить ссылку на ссылку. Это известная
	проблема и Boost предоставляет собственный вариант
	<tt>boost::bind1st</tt>, который решает эту проблему;
	- компилятор Visual C++ 6.0 не смог скомпилировать данный код
	еще и потому, что метод <tt>actor_t::some_method</tt>
	возвращает \c и \c std::mem_fun пытался возвратить результат
	работы <tt>actor_t::some_method</tt> через \c return. В Visual C++
	7.0 такой проблемы нет.

	Проблему с построением ссылки на ссылку можно попробовать
	обойти с помощью <tt>boost::bind1st</tt>:
\code
void
initialize_actor
	( actor_t & actor,
	  const std::list< std::string > & l )
{
	std::for_each
		( l.begin(),
		  l.end(),
		  boost::bind1st
			( std::mem_fun( &actor_t::some_method ),
			  &actor ) );
}
\endcode

	Но и здесь нашлись подводные камни: компилятор Visual C++
	выдавал следующую диагностику:
\verbatim
test\unary_method\boost_way\for_each.cpp(64) : error C2782: 'boost::binder1st<Op
eration> boost::bind1st(Operation &,boost::call_traits<Operation>::param_type)'
: template parameter 'Operation' is ambiguous
        could be 'actor_t *'
        or       'std::const_mem_fun1_t<_Result,_Ty,_Arg>'
        with
        [
            _Result=void,
            _Ty=actor_t,
            _Arg=const std::basic_string<char,std::char_traits<char>,std::alloca
tor<char>> &
        ]
\endverbatim
	Хотя другие компиляторы (Borland C++ 5.6, MinGW 3.0.0) успешно
	компилировали данный код. Visual C++ 6.0 так же выдавал ошибки,
	но свои:
\verbatim
test\unary_method\boost_way\for_each.cpp(64) : error C2784: 'class std::mem_fun_
t<_R,_Ty> __cdecl std::mem_fun(_R (__thiscall _Ty::*)(void))' : could not deduce
 template argument for '<Unknown>' from 'void (__thiscall actor_t::*)(const clas
s std::basic_string<char,struct std::char_traits<char>,class std::allocator<char
> > &) const'
\endverbatim

	А основная проблема была в том, что нужно было использовать
	как раз Visual C++ версий 6.0 и 7.0.
	
	Кроме того, конструкция:
\code
boost::bind1st
	( std::mem_fun( &actor_t::some_method ),
	  &actor )
\endcode
	для вызова метода объекта выглядит не сильно понятной с первого
	взгляда.
	
	Из-за всего вышеизложенного были созданы классы
	cpp_util_2::unary_method_t и cpp_util_2::const_unary_method_t, которые
	позволили решить эту же задачу под всеми имеющимися
	у меня компиляторами:
\code
void
initialize_actor
	( actor_t & actor,
	  const std::list< std::string > & l )
{
	std::for_each
		( l.begin(),
		  l.end(),
		  cpp_util_2::unary_method
		  	( &actor,
			  &actor_t::some_method ) );
}
\endcode

\section	cpp_util_2__unary_method__shortcomming	Недостаток

	По сравнению с реализацией \c boost::bind1st классы
	cpp_util_2::unary_method_t и cpp_util_2::const_unary_method_t
	менее эфективны, т.к. при вызове метода объекта используется
	вспомогательная функция, которая получает дополнительный
	аргумент-указатель. Этот аргумент нигде не используется, поэтому
	хороший оптимизирующий компилятор, наверное, сможет
	простроить не менее эффективный код по сравнению с
	boost::bind1st. Но если оптимизатор не сможет игнорировать
	использование этого параметра, то реализация
	unary_method_t должна проигрывать реализации \c boost::bind1st.
	Но на современной технике и на очень больших количествах
	вызовах этот проигрыш вряд ли составит даже миллисекунды.

*/