如何解决如何让C ++从Lambda推断模板类型参数?
这是我的代码:
#include<iostream>
struct Item {
int val;
};
struct XItem {
int val;
};
void transform(const Item &i,XItem &target) {
target.val = i.val;
}
template<typename T>
void show(const T &v) {
std::cout << v.val << std::endl;
}
template<typename ParamsType,typename ResultType>
void handleRequest(Item &cur,ResultType (*impl)(const ParamsType &p)) {
ParamsType p{};
transform(cur,p);
ResultType res = (*impl)(p);
show(res);
}
struct ResItem {
int val;
};
int main(int argc,char *argv[]) {
Item i{42};
handleRequest(i,[](const XItem &x) {
return ResItem{x.val};
});
return 0;
}
编译它会出现以下错误:
test.cpp:33:3: error: no matching function for call to 'handleRequest'
handleRequest(i,[](const XItem &x) {
^~~~~~~~~~~~~
test.cpp:21:6: note: candidate template ignored: could not match 'ResultType
(*)(const ParamsType &)' against '(lambda at test.cpp:33:20)'
void handleRequest(Item &cur,ResultType (*impl)(const ParamsType &p)) {
^
我不确定为什么会发生这种情况,但是我确实怀疑,因为lambda虽然可以隐式转换为,但它不是一个,所以无法从中推导出模板参数
我尝试改用std::function<ResultType(const ParamsType &p)>
,这也不起作用。 This question详细说明了问题,因此我尝试使用其解决方案:
template<typename ParamsType,typename ResultType,typename Callback>
void handleRequest(Item &cur,Callback cb) {
ParamsType p = transform(cur);
ResultType res = std::invoke(cb,p);
show(res);
}
但是,现在ParamsType
和ResultType
不能从回调中隐式推导出,我需要显式地给它们。但是我真的想推断ResultType
,因为在实际代码中,它可能会很长(它是从lambda return
语句推断出来的,该语句比这个最小的示例更复杂)。我需要这两种类型,因为transform
和show
都被重载,并且需要绑定类型。
在这种情况下是否可以让handleRequest
推断这些类型?如果是,怎么办?
解决方法
问题在于,template argument deduction中未考虑隐式转换(从lambda到函数指针),这无法推断出模板参数。
类型推导不考虑隐式转换(上面列出的类型调整除外):这是overload resolution的工作,以后会发生。
您可以显式指定模板参数以绕过推论,
handleRequest<XItem,ResItem>(i,[](const XItem &x) {
return ResItem{x.val};
});
或将lambda显式转换为函数指针,
handleRequest(i,static_cast<RestItem(*)(const XItem&)>([](const XItem &x) {
return ResItem{x.val};
}));
或使用operator+
将lambda转换为函数指针。
handleRequest(i,+[](const XItem &x) {
return ResItem{x.val};
});
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。