【发布时间】:2015-12-01 18:17:32
【问题描述】:
考虑以下示例:
using function_pair = std::pair<int, void(*)(void*)>; // This line cannot change
template <class Arg, class F>
function_pair make_function_pair(int i, F&& f)
{
return function_pair(i,
[&](void* x){std::forward<F>(f)(static_cast<Arg*>(x));}); // Not working
}
// Later in code
auto p1 = make_function_pair<char>(1, [](char* x){std::cout<<*x<<std::endl;});
auto p2 = make_function_pair<double>(2, [](double* x){*x = *x*2;});
auto p3 = make_function_pair<float>(3, [](float* x){*x = *x*3;});
由于捕获 lambda,代码无法编译(当 lambda 不必捕获 f 时,它可以工作)。我想知道如何在不使用std::function 的情况下完成这项工作,因为std::function 的计算开销很大,我负担不起。即使没有这个实际原因,我也想知道如何在不使用std::function 的情况下解决这个“学术”问题。
【问题讨论】:
-
你需要函数对的第二个元素作为函数指针吗?只有非捕获 lambda 可以转换为 1。 OTOH,如果函数指针只是说明您正在尝试做什么的起点,那么您将面临 C++11 的砖墙。对于 C++14,只需使用
auto作为函数返回类型,就可以避免std::function的开销 -
我第二个 Pradhan -- 由于无法表达返回的 lambda 的类型,您在 C++11 中唯一的选择是在 std::function 或类似的后面擦除它。
-
@Pradhan 是的,我需要一个函数指针,以便 p1、p2 和 p3 都属于同一类型。
-
你测量
std::function的开销了吗?我对此表示怀疑,因为您也是通过引用捕获,当您从当前范围返回 lambda 的副本时,通过引用捕获是一个很大的禁忌。std::function的开销比函数指针大,但如果你在小的函数优化大小范围内,它也不会更离谱。 -
@Pradhan 从
void(char*)转换为void(void*)是未定义的行为。
标签: c++ templates c++11 lambda function-pointers