最近看了老赵的博文,意识到lambda不仅仅提供了一个仿函数的语法糖,而在于能封装环境变量,从而更轻松的实现异步函数调用.
之前利用模板实现过异步函数调用,因为VS2008以前的C++不支持variadic templates和lambda,所以,其实现是用宏实现的0至N个参数的仿函数.因此,本次修改主要是保留以前的代码的基础上,增加lambda的支持.但在获取lambda的返回值的地方费了会儿时间,遂Google之,然后找到这个链接:
http://blog.csdn.net/zwvista/article/details/5531829
为了方便说明,摘抄其内容:
int f() { return 1; }
struct X
{
float operator () () const { return 2; }
// If the following is enabled, program fails to compile
// mostly because of ambiguity reasons.
//double operator () (float i, double d) { return d*f; }
};
template <typename T>
struct function_traits
: function_traits<decltype(&T::operator())> // match X or lambda
{
// This generic template is instantiated on both the compilers as expected.
};
template <typename R, typename C>
struct function_traits<R (C::*)() const> { // inherits from this one
typedef R result_type;
};
template <typename R>
struct function_traits<R (*)()> { // match f
typedef R result_type;
};
template <typename F>
typename function_traits<F>::result_type
foo(F f)
{
return f();
}
int main(void)
{
foo(f);
foo(X());
foo([](){ return 3; });
}
经过测试,这里面提到的方法行不通的,因为
&T::operator()不是T的静态函数.导致编译失败
联想到sizeof(function(x))并不实际调用函数,因此,我认为decltype(function(x))也不会实际调用函数.于是,将
&T::operator()
修改成
decltype(((T*)0)->operator()())
这就在VS2010中顺利编译通过.
完整代码如下:
template<typename LAMBDA>
struct function_traits
{
typedef decltype(((LAMBDA*)0)->operator()()) return_type;
};
template<typename RET>
struct function_traits<RET(*)()>
{
typedef RET return_type;
};
template<typename RET,typename CLASS>
struct function_traits<RET(CLASS::*)() const>
{
typedef RET return_type;
};