这是我能够提出的最小例子:
#include <utility>
template<class CB, class... ARGS>
void call_lam(CB&& cb, ARGS&&... args) {
auto lam = [&args...](auto&& callee) {
callee(std::forward<ARGS>(args)...);
};
lam(cb);
}
void exec(unsigned, int);
void foo() {
unsigned x = 25;
int y = 0;
call_lam(exec, x, y);
}
上面的示例使用CLang和gcc进行编译,但是使用icc 17.0进行编译(如https://godbolt.org/g/tzMY6K所示)。错误如下:
/ usr / include / c ++ / 5 / bits / move.h(89):错误:静态断言失败 使用“模板参数替换_Tp是左值引用类型”
static_assert(!std :: is_lvalue_reference&lt; _Tp&gt; :: value,“template 变量“
^期间检测到:
实例化“_Tp &amp;&amp; std :: forward&lt; _Tp&gt;(std :: remove_reference&lt; _Tp&gt; :: type&amp;&amp;)[with _Tp = unsigned int&amp;]“在”
的第5行实例化函数“lambda [](auto&amp;&amp;) - &gt; auto [with = void(&amp;)(unsigned int,int)]” 在“”
的第7行 实例化“void call_lam”(CB&amp;&amp;,ARGS &amp;&amp; ...)[与CB = void(&amp;)(unsigned int,int),ARGS =]“在第15行”编译中止(代码2)编译器退出,结果代码为2
玩这个例子,我发现:
exec
的参数。当使用两个整数或一个参数时,错误消失std::string
)并将参数传递方式更改为exec
(const&
),可以将错误报告为其他内容,并说“std::move
的重载无法匹配”。此时,它也会在icc16上失败。这是稍加修改的代码:https://godbolt.org/g/qHrU6P 如果代码格式正确(我认为是这样),除了用自定义函子替换lambda(我不想这样做),因为我不想手动捕获带有正确引用的可变数量的参数通过元组)有没有人在这看到任何变通方法?
答案 0 :(得分:0)
我认为以下代码将满足您的解决方法要求:
#include <utility>
#include <iostream>
#include <tuple>
template<class CB, class... ARGS>
void call_lam(CB&& cb, ARGS&&... args) {
auto lam = [](auto&&... args2){
return [&args2...](auto&& callee) {
callee(std::forward<std::tuple_element_t<0, std::decay_t<decltype(args2)>>>(std::get<0>(args2))...);
};}(std::forward_as_tuple(std::forward<ARGS>(args))...);
lam(cb);
}
struct A {
A() {
std::cout << "A()" << std::endl;
}
A(const A&) {
std::cout << "A(const A&)" << std::endl;
}
A(A&&) {
std::cout << "A(A&&)" << std::endl;
}
};
void exec(A &, A) {
}
int main() {
A a;
call_lam(exec, a, A());
}