|
|
10/28/2007
仔细想一下要做一个和boost里的share_ptr类似的带引用计数的智能指针也不是太难,今天下午花了点时间写了一个,支持多线程。
namespace XPtr {
//引用计数模板对象,L 表示所使用的同步对象类型,用作引用计数增减时做同步操作
template<typename L>
class RefCounter {
private:
int counter;
L _lock;
//同步对象操作辅助类,构造函数中加锁,析构函数中解锁
class LockHelper {
private:
L _l;
public:
LockHelper(L &l) { _l = l; _l.lock(); }
~LockHelper() { _l.unlock(); }
};
public:
RefCounter():counter(0) { }
//整形转换操作符
operator int() { return counter; }
//
int operator++() {
LockHelper l(_lock);
return ++counter;
}
//
int operator--() {
LockHelper l(_lock);
return --counter;
}
};
//单线程时的同步对象,全部为空,不做线程同步
struct SingleThread {
void lock() {};
void unlock() {};
};
//主角登场,智能指针模板, T 为指针指向内容,ThreadLock为线程同步策略类,默认为单线程
template<typename T, typename ThreadLock = SingleThread> class xptr{
private:
T * m_ptr;
//引用计数类的指针,指向同一个指针的智能指针要共同维护一个引用计数类实例
RefCounter<ThreadLock> *m_pCounter;
public:
//智能指针可以不初始化,待以后赋值
xptr():m_ptr(0),m_pCounter(0) {}
//用另一个typename P而不直接用T,这样可以支持用子类的指针类初始化父类智能指针
//使用explicit关键字,表示禁止隐式类型转换,防止无意识的情况下把已有的原生指针转成智能指针
template<typename P>
explicit xptr(P *p) { create( new RefCounter<ThreadLock>(), p); }
//拷贝构造函数,若需要支持用子类的智能指针初始化,则需要另外申明一个模板拷贝构造函数,增加一个typename P,类似前面的构造函数
//但由于需要改变引用计数,所以需要智能指针开放接口以取得引用计数对象和原始指针对象,这样会不太雅观,所以这里有个tradeoff (见肥浩的留言)
xptr(const xptr<T> &p) { create(p.m_pCounter,p.m_ptr); }
//赋值操作,同上
const xptr<T>& operator= (const xptr<T> &p) {
if(&p != this) {
destory();
create(p.m_pCounter, p.m_ptr);
}
return *this ;
}
//析构函数,调用destory()辅助函数,用以减少引用计数,并适时销毁原始指针对象和引用计数对象
~xptr() { destory();}
T* operator->() const{ return m_ptr;}
//布尔值转换操作符,判断是否为空
operator bool() { return m_ptr!=0 ; }
private:
//辅助函数,用以增加引用计数,取得原始指针对象和引用计数对象
template<typename P>
void create(RefCounter<ThreadLock> * pf , P* pp) {
m_pCounter = pf;
if(m_pCounter!=0)
++*m_pCounter;
m_ptr = pp;
}
//辅助函数,用以减少引用计数,为零时销毁原始指针对象和引用计数对象
void destory() {
//在多线程环境下这里看似会有同步问题,但是那种情况是不会发生的,所以这样是安全的
if(m_pCounter!=0 && --*m_pCounter==0) {
delete m_pCounter;
delete m_ptr;
}
}
};
}
要用在多线程环境中的话需要根据平台实现一个同步类,内部有一个mutex,支持lock, unlock操作,使用时将此同步类作为智能指针的第二个模板参数即可。 5/28/2007
接上文,_2 _3 的实现。 没想到自己居然这么勤快
//////////////////////////////////////////////// // lambda templates namespace XLambda { template <typename T> class CXLambdaLiteral { public: CXLambdaLiteral(const T &t): m_data(t) {} template <typename V> inline V operator() (const V &x) const {return m_data;} template <typename V> inline V operator() (const V &x,const V &y) const {return m_data;} template <typename V> inline V operator() (const V &x,const V &y,const V &z) const {return m_data;} private: T m_data; };
class CXLambdaIdentity { public: template <typename V> inline V operator() (const V &x) const {return x;} template <typename V> inline V operator() (const V &x,const V &y) const {return x;} template <typename V> inline V operator() (const V &x,const V &y,const V &z) const {return x;} };
class CXLambdaIdentity_2 { public: template <typename V> inline V operator() (const V &x,const V &y) const {return y;} template <typename V> inline V operator() (const V &x,const V &y, const V &z) const {return y;} };
class CXLambdaIdentity_3 { public: template <typename V> inline V operator() (const V &x,const V &y,const V &z) const {return z;} };
template <class A,class B,class Op> class CXLambdaBinOp { public: CXLambdaBinOp(const A &a,const B &b):m_a(a),m_b(b) {} template <class V> inline V operator() (const V &x) const {return Op::apply(m_a(x),m_b(x));} template <class V> inline V operator() (const V &x,const V &y) const {return Op::apply(m_a(x,y),m_b(x,y));} template <class V> inline V operator() (const V &x,const V &y,const V &z) const {return Op::apply(m_a(x,y,z),m_b(x,y,z));} private: A m_a; B m_b; };
template <class T> class CXLambda { public: CXLambda(const T &t):m_t(t) {} CXLambda() {}; template<class V> inline V operator()(const V &x) const {return m_t(x);} template<class V> inline V operator()(const V &x, const V &y) const {return m_t(x,y);} template<class V> inline V operator()(const V &x, const V &y, const V &z) const {return m_t(x,y,z);} private: T m_t; };
///////////////////////////////////////////////////////////////////////////////// // 用宏实现重复的运算符重载工作, 宏定义略,参见上篇
OP_BIN(Add, +) OP_BIN(Sub, -) OP_BIN(Multiply, *) OP_BIN(Divid, /)
///////////////////////////////////////////////////////////////////////////////// //为方便使用而定义的宏 #define _1 CXLambda<CXLambdaIdentity>() #define _2 CXLambda<CXLambdaIdentity_2>() #define _3 CXLambda<CXLambdaIdentity_3>()
}
/////////////////////////////////////////////////////////////////////////// // test, 一个三元参数的函数对象(一个匿名的functor)的诞生和计算 printf(" %d ",(_1 + _2*_2 + _3*_3*_3+ 1 + _2*10)(1,2,3));
一个自制Lambda诞生了!和boost里一样好用,呃,好像似乎差不多啦... 因为boost里的lambda我也没怎么用过,不知道人家还有什么特异功能 5/27/2007 换工作以来一直用J2ME, 很久没碰C++了,非常怀念它的强大灵活。STL, templates, boost ... 工作就是这样,很无奈,为了混口饭吃就顾不了那么多了,用什么语言不要紧,只要给钱就行。公司有人原来用Java来了之后用C++,有人原来用C++来了之后用Java,有人原来用Java来了之后用C#... 晕死。 最近看到书上讲用C++ tempaltes 实现lambda, 还提到了boost,一时手痒就自己写了个,仿照boost里的 _1 。除了“_1”这两个字符外没有参考其它任何实现。基本原理和我之前写的expression templates实现差不多。 暂时只实现了一元变量,还不支持_2 _3,和强大到让人目瞪口呆的boost相比只是小儿科啦。什么时候有空再做 _2
//////////////////////////////////////////////// // lambda templates namespace XLambda { template <typename T> class CXLambdaLiteral { public: CXLambdaLiteral(const T &t): m_data(t) {} template <typename V> inline V operator() (const V &x) const {return m_data;} private: T m_data; };
class CXLambdaIdentity { public: template <typename V> inline V operator() (const V &x) const {return x;} };
template <class A,class B,class Op> class CXLambdaBinOp { public: CXLambdaBinOp(const A &a,const B &b):m_a(a),m_b(b) {} template <class V> inline V operator() (const V &x) const {return Op::apply(m_a(x),m_b(x));} private: A m_a; B m_b; };
template <class T> class CXLambda { public: CXLambda(const T &t):m_t(t) {} CXLambda() {}; template<class V> inline V operator()(const V &x) const {return m_t(x);} private: T m_t; };
///////////////////////////////////////////// struct XOpAdd { template<typename V> inline static V apply(const V&x, const V &y) { return x+y; } };
template <typename A, typename B> CXLambda<CXLambdaBinOp<CXLambda<A>, CXLambda<B>, XOpAdd> > operator +(const CXLambda<A> &a,const CXLambda<B> &b) { typedef CXLambdaBinOp<CXLambda<A>, CXLambda<B>, XOpAdd> LamT; return CXLambda<LamT>(LamT(a,b)); }
template <typename A, typename B> CXLambda<CXLambdaBinOp<CXLambda<A>, CXLambda<CXLambdaLiteral<B> >, XOpAdd> > operator +(const CXLambda<A> &a,const B &b) { typedef CXLambdaBinOp<CXLambda<A>, CXLambda<CXLambdaLiteral<B> >, XOpAdd> LamT; return CXLambda<LamT>(LamT(a,CXLambdaLiteral<B>(b))); }
template <typename A, typename B> CXLambda<CXLambdaBinOp<CXLambda<B>, CXLambda<CXLambdaLiteral<A> >, XOpAdd> > operator +(const A &a,const CXLambda<B> &b) { typedef CXLambdaBinOp<CXLambda<B>, CXLambda<CXLambdaLiteral<A> >, XOpAdd> LamT; return CXLambda<LamT>(LamT(b,CXLambdaLiteral<A>(a))); }
///////////////////////////////////////////// struct XOpMultiply { template<typename V> inline static V apply(const V&x, const V &y) { return x*y; } };
template <typename A, typename B> CXLambda<CXLambdaBinOp<CXLambda<A>, CXLambda<B>, XOpMultiply> > operator *(const CXLambda<A> &a,const CXLambda<B> &b) { typedef CXLambdaBinOp<CXLambda<A>, CXLambda<B>, XOpMultiply> LamT; return CXLambda<LamT>(LamT(a,b)); }
template <typename A, typename B> CXLambda<CXLambdaBinOp<CXLambda<A>, CXLambda<CXLambdaLiteral<B> >, XOpMultiply> > operator *(const CXLambda<A> &a,const B &b) { typedef CXLambdaBinOp<CXLambda<A>, CXLambda<CXLambdaLiteral<B> >, XOpMultiply> LamT; return CXLambda<LamT>(LamT(a,CXLambdaLiteral<B>(b))); }
template <typename A, typename B> CXLambda<CXLambdaBinOp<CXLambda<B>, CXLambda<CXLambdaLiteral<A> >, XOpMultiply> > operator *(const A &a,const CXLambda<B> &b) { typedef CXLambdaBinOp<CXLambda<B>, CXLambda<CXLambdaLiteral<A> >, XOpMultiply> LamT; return CXLambda<LamT>(LamT(b,CXLambdaLiteral<A>(a))); }
//减法和除法可以依样画葫芦
//一元操作符++ 等 和函数如sin cos log, 也比较简单 可以参考之前的expression template
#define _1 CXLambda<CXLambdaIdentity>() }
//////////////////////////////////////////////// //使用测试 using namespace XLambda; vector<int> t; for(int i=0;i<10;i++) t.push_back(i);
//vector中的值就会根据这个计算式改变了! transform(t.begin(),t.end(),t.begin(),1000 + 100 * _1 + _1*10); //或 transform(t.begin(),t.end(),t.begin(), _1 * _1 * _1);
以后会实现 _2, 如果我不是太懒的话。
2/13/2007
////////////////////////////////////////////////////////////////////////// // 曾经根据Todd Veldhuizen的论文 Expression Templates 写的一份代码实现, // http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html // 不包括矩阵计算部分
namespace XExp { #include <math.h>
//constant expression template template <class T> class CXExpLiteral { public: CXExpLiteral(const T &t):m_data(t) {} template <class V> inline V operator() (const V &x) const {return m_data;} private: T m_data; };
//variable expression(the 'x' in a fomular) template template <class T> class CXExpIdentity { public: template <class V> inline V operator() (const V &x) const {return x;} };
//binary operator template template <class A,class B,class Op> class CXBinExpOp { public: CXBinExpOp(const A &a,const B &b):m_a(a),m_b(b) {} template <class V> inline V operator() (const V &x) const { return Op::apply(m_a(x),m_b(x)); }
private: A m_a; B m_b; };
//unary operator template template <class A,class Op> class CXUnaExpOp { public: CXBinExpOp(const A &a):m_a(a) {} template <class V> inline V operator() (const V &x) const { return Op::apply(m_a(x)); }
private: A m_a; };
//static polymorphic interface template (this is only my own notion, maybe not a standard common concept) template <class T> class CXExp { public: CXExp(const T &t):m_t(t) {} CXExp() {};
//static polymorphic interface(like a virtual function) template<class V> inline V operator()(const V &x) const { return m_t(x); }
private: T m_t; };
//utility //function template to create a constant expression template <class V> inline CXExp<CXExpLiteral<V> > mk_literal(const V &l) { return CXExpLiteral<V>(l); }
//the variable expression (the 'x' in a fomular again) typedef CXExp<CXExpIdentity> ExpX;
//function template to evaluate the end expression template <class Exp,class V> V xeval(const CXExp<Exp> &exp,const V&x) { return exp(x); }
////////////////////////////////////////////////////////////////////////// //binary operator //macro definition for the binary operator and the binary expression template class #define OP_BIN(_name,_op) \ struct XOp##_name { \ template<class V> \ inline static V apply(const V &x,const V &y) \ { return x _op y;} }; \ template <class A,class B> \ CXExp<CXBinExpOp<CXExp<A>,CXExp<B>,XOp##_name> > \ operator _op(const CXExp<A> &a,CXExp<B> &b) { \ typedef CXBinExpOp<CXExp<A>,CXExp<B>,XOp##_name> ExpT; \ return CXExp<ExpT>(ExpT(a,b)); }
OP_BIN(Divid,/) OP_BIN(Multipy,*) OP_BIN(Add,+) OP_BIN(Sub,-) //...
////////////////////////////////////////////////////////////////////////// //unary operator #define OP_UNA_FUNC(_fun) \ struct XOp##_fun { \ inline static double apply(double x) \ { return _fun(x);} }; \ template <class A> \ CXExp<CXUnaExpOp<CXExp<A>,XOp##_fun> > \ _fun(const CXExp<A> &a) { \ typedef CXUnaExpOp<CXExp<A>,XOp##_fun> ExpT; \ return CXExp<ExpT>(ExpT(a)); }
OP_UNA_FUNC(log) OP_UNA_FUNC(log10) OP_UNA_FUNC(sin) //... }
////////////////////////////////////////////////////////////////////////// /* usage
ExpX x; cout << xeval((mk_literal(1.0)+x)/sin(x),1.2);
*/
|