{
public:
void notify()
{
myHandler();
}
std::string myString;
};
{
public:
int OnNotify()
{
std::cout << "Observer::OnNotify" << std::endl;
return 0;
}
};
{
Subject subject;
Observer observer;
subject.myString = "changed";
subject.notify();
#define _DELEGATE_FUNC(count) _DELEGATE_FUNC_P(count)
_DELEGATE_FUNC_P(PARAM_COUNT)
class mem_fun1_t{
public:
explicit mem_fun1_t(_R (_Ty::*_Pm)(_A))
: _Ptr(_Pm){}
private:
_R (_Ty::*_Ptr)(_A);
};
// TEMPLATE FUNCTION mem_fun1
template<class _R, class _Ty, class _A> inline
mem_fun1_t<_R, _Ty, _A> mem_fun1(_R (_Ty::*_Pm)(_A))
{return (mem_fun1_t<_R, _Ty, _A>(_Pm)); }
4、【技巧】现在遇到的问题是,虽然通过函数模板,在函数内可以提取出类的名字,生成对象,但是该对象如果需要保存下来,下次调用的时候又无法知道开始的时候是什么类了。举个例子来说明问题所在:在delegate类中保存了CTest的指针强制转换成了void*后面需要调用CTest的函数,需要把void*指针重新转换成CTest的指针,可是delegate类并不知道CTest类,这怎么办呢?方法是使用了一个类和静态函数的方法,静态函数的形式是固定的,这样就可以保存下CTest类的类型了,下面是示例:
template<typename FuncPtr, typename _R, typename T1>
struct delegate_h{
static _R invoker(void* p, T1 i)
{
FuncPtr* mp= (FuncPtr*)p;
return (*mp)(i);
}
};
template<class _R, class _A1>
class delegate{
public:
typedef _R(*FuncPtr)(_A1);
template<typename Mem>
delegate(Mem& f)
{
m_mem = new Mem(f);
invoker = delegate_h<Mem,_R, _A1>::invoker;
}
_R operator() (_A1 a)
{
return invoker(m_mem, a);
}
private:
void* m_mem;
typedef _R (*invoke_type)(void*, _A1);
invoke_type invoker;
};
5、【技巧】宏定义进行重复,这个是为了降低工作量的,因为对于不同的参数个数,需要定义不同的类,因此需要重复的代码,这个非常不好,我们可以使用宏定义来进行重复。比如需要生成3个参数的模板就需要template<typename R, typename A1, typename A2, typename A3>,如何通过简单的代码生成任意长度的列表呢?
#define BOOST_PP_REPEAT(n, m, p) BOOST_PP_REPEAT ## n(m, p)
#define BOOST_PP_REPEAT0(m, p)
#define BOOST_PP_REPEAT1(m, p) m(0, p)
#define BOOST_PP_REPEAT2(m, p) m(0, p) m(1, p)
#define BOOST_PP_REPEAT3(m, p) BOOST_PP_REPEAT2(m, p) m(2, p)
#define BOOST_PP_REPEAT4(m, p) BOOST_PP_REPEAT3(m, p) m(3, p)
#define BOOST_PP_REPEAT5(m, p) BOOST_PP_REPEAT4(m, p) m(4, p)
....
//typename A1, typename A2, typename A3
#define DEFINE_TYPENAME(i, k) MY_COMMA_I(BOOST_PP_BOOL_I(i)) typename A##i
#define REPEAT_TYPENAME(count) REPEAT_TYPENAME_I(count)
#define REPEAT_TYPENAME_I(count) BOOST_PP_REPEAT(count, DEFINE_TYPENAME, count)
6、【技巧】上面的例子里面使用了BOOST_PP_BOOL_I(i),这个是一个条件语句,表示第一个参数前面不要加逗号,这个是因为这个重复出来的字符串,可能作为operator()的参数,那么参数列表的第一个参数前面不能有逗号,而重复出来的代码肯定有,所以需要通过条件宏来解决,第一个不加逗号。下面是条件宏的实现:
//BOOST BOOL
#define BOOST_PP_BOOL_I(x) BOOST_PP_BOOL_ ## x
#define BOOST_PP_BOOL_0 0
#define BOOST_PP_BOOL_1 1
#define BOOST_PP_BOOL_2 1
#define BOOST_PP_BOOL_3 1
#define BOOST_PP_BOOL_4 1
#define BOOST_PP_BOOL_5 1
......
#define MY_COMMA(bit) MY_COMMA_##bit
#define MY_COMMA_I(count) MY_COMMA(count)
#define MY_COMMA_0
#define MY_COMMA_1 ,
7、【基础】使用模板函数之后如果希望对特定的类型做不同的处理,那么这个特定的函数一定需要在模板函数后面定义,否则就会出现二意性。
8、【技巧】重复引用同一个文件,给定不同的宏定义,这样可以生成很多个类,用来生成delegate0, delegate1, delegate2....下面是一个例子:
#include "funcbase.h"
#include <stdio.h>
#include <vector>
#define PARAM_COUNT 0
#include "function_temp.h"
#undef PARAM_COUNT
#define PARAM_COUNT 1
#include "function_temp.h"
#undef PARAM_COUNT
9、【问题】最后的问题是返回值必须不能是void,因为对于void类型的返回return后面不能跟任何的东西,解决的方法是定义result_type把void进行封装,返回一个不需要的类型,但是这样需要增加不少代码,故我没有采用这个方法。
好了,现在已经完整的讲了boost::function实现过程中会碰到的问题,也温习了一些知识点,相信这个对于boost的描述和很多其它的资料很不同:)。
PS:讲个自己的故事,记得以前还在上大学的时候,勤工俭学需要对一批WORD文档进行同样的编辑处理,我当时仅会最简单的WORD编辑,因此我用我自己的知识加上勤奋的双手奋斗了一个通宵完成了任务。第二天我们班一个精通电脑的家伙看我很辛苦,就帮我研究了一下WORD,然后让我使用一些自动的工具,大幅度的提高了效率!这个给我很深的印象,我们很多时候都只是在使用最简单的技术搭建巨大的应用,却不愿意多花10分钟学习一下,以提高效率,这是可悲的。
PS2:这里不能加附件,如果需要源代码的可以和联系,代码比较简单。另外有志同道合的也希望多多交流加个链接哦~ oeichenwei@gmail.com