提问人:bradgonesurfing 提问时间:9/28/2021 更新时间:9/28/2021 访问量:121
为什么我无法推断出可变 lambda 的函数签名?
Why can't I deduce the function signature for a mutable lambda?
问:
我有以下代码来实现 memoize 函数。
注意问题不在于如何专门编写一个记忆函数,而在于我在这个实现中得到的编译错误以及让它工作的最小更改。
实现。
#include <functional>
#include <map>
#include <functional>
#include <iostream>
using namespace std;
template<typename T>
struct memfun_type
{
using type = void;
};
template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const>
{
using type = std::function<Ret(Args...)>;
};
template<typename F>
typename memfun_type<decltype(&F::operator())>::type
FFL(F const &func)
{ // Function from lambda !
return func;
}
template <typename ReturnType, typename... Args>
std::function<ReturnType (Args...)>
memoizeImp(std::function<ReturnType (Args...)> func)
{
std::map<std::tuple<Args...>, ReturnType> cache;
return ([=](Args... args) mutable {
std::tuple<Args...> t(args...);
if (cache.find(t) == cache.end())
cache[t] = func(args...);
return cache[t];
});
}
template <typename Fn>
auto memoize(Fn && fn){
return memoizeImp(FFL(fn));
}
和测试程序
int main()
{
auto a = 2.;
auto foo = [a](double x){return x+a;};
auto foom = memoize(foo);
std::cout << foo(1) << std::endl;
std::cout << foom(1) << std::endl;
}
预期的输出为
3
3
但是,如果我对测试程序进行小的更改,则更改
auto foo = [a](double x){return x+a;};
自
auto foo = [a](double x)mutable{return x+a;};
我在 gcc 上收到以下编译错误
Could not execute the program
Compiler returned: 1
Compiler stderr
<source>: In instantiation of 'auto memoize(Fn&&) [with Fn = main()::<lambda(double)>&]':
<source>:49:24: required from here
<source>:42:26: error: invalid use of void expression
42 | return memoizeImp(FFL(fn));
| ~~~^~~~
<source>: In instantiation of 'typename memfun_type<decltype (& F::operator())>::type FFL(const F&) [with F = main()::<lambda(double)>; typename memfun_type<decltype (& F::operator())>::type = void; decltype (& F::operator()) = double (main()::<lambda(double)>::*)(double)]':
<source>:42:26: required from 'auto memoize(Fn&&) [with Fn = main()::<lambda(double)>&]'
<source>:49:24: required from here
<source>:24:12: error: return-statement with a value, in function returning 'memfun_type<double (main()::<lambda(double)>::*)(double)>::type' {aka 'void'} [-fpermissive]
24 | return func;
| ^~~~
失败的代码和编译错误可以在 https://godbolt.org/z/74PKWvqr4 查看和测试
我不确定让它与可变 lambda 一起使用的解决方法是什么。
答:
评论
memfun_type<Ret(Class::*)(Args...)>
3 3
mutable
mutable