c++ - 将 lambda 传递给可变参数 std::function 时的类型推导
问题描述
我正在尝试使用用于处理它们的函数的类型信息从数组元组中检索值。但是,在这种情况下,类型推导失败(部分原因是?)因为需要对std::function
. 有没有办法在这里恢复扣除?
#include <functional>
#include <iostream>
#include <tuple>
class comp_a
{
public:
static const size_t id = 0;
int val = 0;
};
class comp_b
{
public:
static const size_t id = 1;
int val = 0;
};
class comp_c
{
public:
static const size_t id = 2;
int val = 0;
};
template<size_t size, typename ... Cs>
struct storage
{
template<typename T> struct identity { using type = T; };
template<typename ... Ts>
void get(size_t index, typename identity<std::function<void(Ts& ...)>>::type f)
{
f(std::get<Ts::id>(components)[index] ...);
}
std::tuple<std::array<Cs, size> ...> components;
};
int32_t main()
{
storage<20, comp_a, comp_b, comp_c> storage;
storage.get(2, [](comp_a& a, comp_c& c) { // Doesn't work
// storage.get<comp_a, comp_c>(2, [](comp_a& a, comp_c& c) { // Works
std::cout << a.val << " " << c.val << std::endl;
});
}
我遇到过this和this,它们看起来很相似,但我相信我的情况有所不同,因为我需要可变参数类型才能在检索所需值时访问它们的特征。在这些示例中,函数的可变参数被视为 void:
error: cannot convert 'main()::<lambda(comp_a&, comp_c&)>' to 'storage<20, comp_a, comp_b, comp_c>::identity<std::function<void()> >::type' {aka 'std::function<void()>'}
在这种情况下,扣除指南是否可行?类型信息似乎隐藏在 的类型中有点深std::function
,所以我不确定如何在指南中将其提取出来。
这里有一个活生生的例子。
解决方案
您可以使用std::function
演绎指南技巧来提取参数,但您真的不想实际创建一个std::function
. 您想在 lambda-land 中堆叠。std::function
由于类型擦除而增加了开销和分配 - 但是您所做的任何事情实际上都不需要类型擦除提供的好处。都是输,没有赢。实际上不要制作std::function
.
也就是说,您当然仍然需要这些论点。所以你可以这样做:
template <typename T> struct type { };
template <typename F>
void get(size_t index, F f) {
using function_type = decltype(std::function(f));
get_impl(index, f, type<function_type>{});
}
基本上,我们采用一些可调用的 - 然后我们std::function
从中推断出 a。这给了我们一些类型。在 OP 中的具体示例中,该类型是std::function<void(comp_a&, comp_b&)>
. 然后,我们只需将该类型转发给不同的函数——作为一个空对象。没有开销。重复一遍,我们实际上并没有创建一个std::function
- 我们只是传递它的类型。
该其他功能可以利用知道什么std::function
知道:
template <typename T> using uncvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template <typename F, typename R, typename... Args>
void get_impl(size_t index, F f, type_t<std::function<R(Args...)>>) {
f(std::get<uncvref_t<Args>::id>(components)[index] ...);
}
您需要uncvref_t
那里来处理Args
可能是也可能不是参考或cv合格的情况。
现在,这对任何可调用对象都不起作用。如果你传入一个通用的 lambda,推导std::function
将失败。但是……那无论如何也行不通,所以看起来损失不大?
推荐阅读
- python - conda 更新 conda,崩溃
- batch-file - Windows 命令提示符中的 if command -> set -> echo 出现问题
- python - Python,检测是否重复进程正在运行
- multithreading - mod_wsgi 中的服务器发送事件 (SSE) 阻塞线程
- jquery - 无法关闭移动设备上的下拉菜单
- image - Scrapy不下载图像
- reactjs - 如何在 WebStorm 中调试 React 应用程序?
- c++ - 使用 static_cast 来实现动态多态性
- reactjs - 如何在使用反应钩子时初始化第三方库?
- android - 如果我想用语音和画布在屏幕上记录整个屏幕活动以通过触摸写任何东西,该研究什么?