为什么要使用指向成员函数的可变lambda表达式?

3
我想要获取一个lambda函数中的operator()。以下内容似乎可以完成这个任务:
template <typename F>
void bar(F func) {
  void (F ::*pm)();
  pm = &F::operator();
}

然而,在接下来的内容中,我需要包含 "mutable" 关键字。为什么会这样?是否可以声明指向成员函数的指针,以便可以针对任意的 lambda 表达式?
int main(int argc, char *argv[])
{
  bar([]() mutable {});
  return 0;
}

什么错误?也许 lambda 的运算符是 const,你能把它添加到你的函数指针中吗? - Kerrek SB
3个回答

8
根据N3291 C++0x规范的5.1.2,除非您明确声明为mutable,否则lambda的operator()是const:

仅当lambda表达式的parameter-declaration-clause后面没有带有mutable时,此函数调用运算符才被声明为const (9.3.1)。

您可以使用一些模板元编程技巧来检测哪个是哪个。
但是,请注意,一旦func超出作用域,就不能再使用该成员指针。它是成员指针,而不是函数指针,因此无法在两者之间进行转换。

4

C++0x的lambda函数默认为const,与语言中的其他部分不同。因此,您的成员函数变量也必须是const。以下代码应该可以正常工作:

template<typename F>
void bar(F func) {
    typedef void (F::*pm_t)() const;
    pm_t pm = &F::operator();
}

哎呀,使用mutable也不行:错误:无法将‘void (main(int, char**)::<lambda()>::*)()’转换为‘pm_t {aka void (main(int, char**)::<lambda()>::*)()const}’进行初始化 - user2023370
@user643722:使用哪个版本的编译器?在GCC 4.5.1上运行良好 - ildjarn
好的,没有“mutable”也能工作,加一分。但是我能否有一个指向函数的指针,它可以指向“mutable”或“const”? - user2023370
1
@user643722:当然,使用decltype而不是自己的typedef,这样编译器就可以自行推断operator()的签名。或者你是在问如何确定它是否为const,而不使用decltype - ildjarn
@ildjarm:当然。实际上,auto 也可以帮助我们:auto pp = &F::operator(); - user2023370

1

考虑一下:

int x=0;
auto show = [x]() mutable
{
        x++;
};

show();

变量'x'被以值传递的方式捕获,如果没有mutable,则无法修改此变量的本地副本。指定mutable以启用对此本地副本的修改。对于按值捕获,即使值被修改,原始的x变量也不会被修改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接