vc2010 新增加的特性:lambda表达式,auto关键字,typedecl关键字,rvalue reference,shared_ptr都是很强大的语法/库特性.
下面的小程序仿照泛函实现,写了个非常简陋的代理实现。不支持void返回值,只支持一个参数。不过新的特性基本都用上了。
PS:记得上一次写模板代码还是在皿鎏的时候,好久没动手了,呵呵。
// Copyright 2010.4.17 yangjie82@gmail.com 3dijoy.com
#include <crtdbg.h>
#include <cstdlib>
#include <memory>
#include <iostream> // NOLINT
#include <vector>
#include <algorithm>
#include <iterator>
#include <type_traits> // NOLINT
using namespace std; // NOLINT
template <class _TyRet, class _TyP0, class _TyWorker, class _TyMemFunPtr>
_TyRet&& caller(void* worker, void* memFunPtr, _TyP0&& p0) {
_TyWorker* w = reinterpret_cast< _TyWorker* >(worker);
_TyMemFunPtr m = reinterpret_cast< _TyMemFunPtr >(*reinterpret_cast< _TyMemFunPtr* >(memFunPtr));
return (w->*m)(p0);
}
template< class _TyMemFunPtr >
void cleaner(void* memFunPtr) {
delete reinterpret_cast< _TyMemFunPtr** >(memFunPtr);
}
template <class _TyRet, class _TyP0>
class _delegate_impl {
static_assert(!tr1::is_void< _TyRet >::value, "void return type hasn't been supported now!");
private:
void* worker_;
void* memFunPtr_;
void* caller_;
void(*cleaner_)(void*); // NOLINT
public:
template <class _TyWorker>
explicit _delegate_impl(_TyWorker* worker, _TyRet(_TyWorker::*memFunPtr)(_TyP0)) :
worker_(worker),
memFunPtr_(new (_TyRet(_TyWorker::*)(_TyP0))(memFunPtr)) {
caller_ = &caller< _TyRet, _TyP0, _TyWorker, _TyRet(_TyWorker::*)(_TyP0) >;
cleaner_ = &cleaner< _TyRet(_TyWorker::*)(_TyP0) >;
}
~_delegate_impl() {
reinterpret_cast< void(*)(void*) >(cleaner_)(memFunPtr_); // NOLINT
}
_TyRet&& operator()(_TyP0&& p0) {
return reinterpret_cast< _TyRet&&(*)(void*, void*, _TyP0&&)>(caller_) // NOLINT
(worker_, memFunPtr_, static_cast<_TyP0&& >(p0));
}
};
template <class _TyRet, class _TyP0>
class _delegate {
private:
typedef _delegate_impl<_TyRet, _TyP0> impl_type;
shared_ptr< impl_type > impl_;
public:
template <class _TyWorker>
explicit _delegate(_TyWorker* worker, _TyRet(_TyWorker::*memFunPtr)(_TyP0)) :
impl_(new impl_type(worker, memFunPtr)) {
}
explicit _delegate(_delegate&& rhs) {
*this = move(rhs);
}
_delegate& operator=(_delegate&& rhs) {
if (this != &rhs) {
impl_ = move(rhs.impl_);
}
return *this;
}
auto operator()(_TyP0&& p0)->decltype(impl_->operator()(static_cast< _TyP0&& >(p0))) {
return impl_->operator()(static_cast< _TyP0&& >(p0));
}
};
struct sValue0 {
int foo(int x) {
cout<< "sValue0:foo" << x << endl;
return x;
}
};
void main() {
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
{
sValue0 v0;
typedef _delegate< int, int > fooEventHandler;
vector< fooEventHandler > handlers;
generate_n(back_inserter(handlers), 10, [&v0, &handlers]()->fooEventHandler {
return fooEventHandler(&v0, &sValue0::foo);
});
for_each(handlers.begin(), handlers.end(), [](fooEventHandler& f)->decltype(f(0)) { // NOLINT
return f(0);
});
}
_ASSERTE(_CrtCheckMemory());
_ASSERTE(!_CrtDumpMemoryLeaks());
system("pause");
}