【问题标题】:Why can't I deduce the function signature for a mutable lambda?为什么我不能推断出可变 lambda 的函数签名?
【发布时间】:2021-09-28 13:22:25
【问题描述】:

我有以下实现 memoize 功能的代码。

注意问题不在于如何专门编写 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&lt;Ret(Class::*)(Args...)&gt; 的专业化(非 const 方法)。
  • 3 3 输出不正确?这只是一个简化的示例,实际上不需要mutable lambda,但您想为更一般的情况启用mutable lambda?
  • @463035818_is_not_a_number 是的。问题是可变的而不是函数本身的主体。

标签: c++ lambda c++14 variadic-templates mutable


【解决方案1】:

你缺乏专长。

Adding this makes it work

template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...)>
{
    using type = std::function<Ret(Args...)>;
};

如果 lambda 未声明 mutable,则 lambda 的闭包类型的 operator()const 限定的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多