lambda和std :: function之间的强制转换(关于结构继承自身偏特化版本)

jeff_
  • 41

关于C++ 特性不太熟悉,谷歌也因为不知道具体关键字而造成困难,于是又来请教大家。

代码是关于 lambda和std :: function之间的 无法进行强制转换 ,于是手动识别lambda 进行转换。

下面这里的结构体function_traits继承一个偏特化的版本是什么意思?

template <typename Function>
struct function_traits : public function_traits<decltype(&Function::operator())> {

};

原文链接(需fan墙):http://vitiy.info/c11-functional-decomposition-easy-way-to-do-aop/

测试代码(备注均为我自己添加,可能有错误)
#include <iostream>
#include <functional>

//using namespace std;

template <typename ...Args>
std::function<void(Args...)> wrapLog(std::function<void(Args...)> f) {

    return [f](Args... args) {                                            //捕获函数对象f
        std::cout << "start" << std::endl;
        f(args...);
        std::cout << "finish" << std::endl;
    };
}

template <typename Function>
struct function_traits : public function_traits<decltype(&Function::operator())> {

};

//lambda 转换为 std::function<void(Args...)> 需要知道 传入参数类型和返回值类型 ,这里进行萃取 
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>         //Args...可变模板参数 ,因为不知道lambda将传入几个参数
{
    //typedef ReturnType (*pointer)(Args...);
    typedef std::function<ReturnType(Args...)> function;            
};


template <typename Function>
typename function_traits<Function>::function    //返回值类型 function_traits<Function>::function
to_function(Function& lambda)                    //函数名to_function,传入参数lambda
{
    return typename function_traits<Function>::function(lambda);    //将lambda传入function_traits<Function>::function 
}

//functional里面有定义了个std::plus。如果把plus定义为global的,访问时在global查找定义就会和std::plus冲突,产生二义。
//auto plus = [](int a, int b) { std::cout << a + b << std::endl; };            //error,Plus不明确
std::function<void(int, int)> plus = [](int a, int b) { std::cout << a + b << std::endl; };

int main(int argc, char *argv[]) {
    //这是简单的lambda,其中包含琐碎的计算:
    //auto plus = [](int a, int b) { cout << a + b << endl; };

    //lambda和 std :: function 无法完成转换
    //auto loggedPlus = wrapLog(plus);                                                //test1

    //强制转换,OK,该行可以编译,但是很难看
    auto loggedPlus  = wrapLog(static_cast<std::function<void(int, int)>>(plus));   //test2
    loggedPlus(2, 3);

    //暂时最佳解决方案
    auto loggedPluss = wrapLog(to_function(plus));            //通过调用to_function函数 将 lambda表达式plus 转换为std::function<void(Args...)> 形式
    loggedPluss(2, 3);

    return 0;
}
回复
阅读 1.7k
1 个回答
✓ 已被采纳

它并不一定要继承自己的偏特化。换一个也可以,比如这样

template <typename> struct function_traits_base;

template <typename Function>
struct function_traits : public function_traits_base<decltype(&Function::operator())> {

};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_base<ReturnType(ClassType::*)(Args...) const>       {
    typedef std::function<ReturnType(Args...)> function;            
};

这样看得清楚一些,function_traits 是对外接口,但是需要 function_traits_base 的辅助来获得其对应得 std::function 特化。

这里,由于 function_traitsfunction_traits_base 都是只有一个类型模板参数,其生效得类型无交集(function_traits 只用于(实现了 operator() 的)类类型,function_traits_base 只用于指向成员函数的指针),所以原来的实现里就都使用了 function_traits ,没有引入另外的一个类型。

你知道吗?

宣传栏