C ++:强制lamba实例具有唯一的静态变量

bre*_*att 7 c++ lambda c++14

我想创建一个生成lambda的函数,其中每个lambda都有自己的静态变量。但是,与我的想法相反,静态变量似乎在实例之间共享。例如,

#include <iostream>

auto make_lambda(){
    return [](){
        static auto count = 0;
        return count++;
    };
}

int main() {
    auto a = make_lambda();
    auto b = make_lambda();
    std::cout << &a << ", " << a() << std::endl;
    std::cout << &b << ", " << b() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

退货

0x7ffc229178df, 0
0x7ffc229178de, 1
Run Code Online (Sandbox Code Playgroud)

因此ab似乎是唯一的实例,但它们共享该静态计数。我以为我会看到并且确实希望看到类似

0x7ffc229178df, 0
0x7ffc229178de, 0
Run Code Online (Sandbox Code Playgroud)

现场演示

确保每个lambda都有自己的静态变量的最简单方法是什么?

Que*_*tin 11

抛弃静态变量并使用扩展的lambda捕获:

#include <iostream>

auto make_lambda(){
    return [count = 0]() mutable {
        return count++;
    };
}
Run Code Online (Sandbox Code Playgroud)

如果您希望不同的lambda实例与其各自的副本共享状态,而不是在它们之间共享状态,则可以std::shared_ptr改用:

auto make_lambda(){
    return [count = std::make_shared<int>(0)]() mutable {
        return (*count)++;
    };
}
Run Code Online (Sandbox Code Playgroud)

  • @Quentin-同意这是我无法明确其目的的要求,但是如果那是OP想要的:) (3认同)
  • @StoryTeller怪异的功能,但是您去了。 (2认同)

Sto*_*ica 6

您可以利用以下事实:实例化函数以及它们所包围的模板化实体在函数中定义了自己的静态变量副本。正在make_lambda变成范本...

template<int>
static auto make_lambda(){
    return [](){
        static auto count = 0;
        return count++;
    };
}
Run Code Online (Sandbox Code Playgroud)

...将为每个新的模板参数生成一个新的静态变量,该变量对于TU是唯一的(由于函数模板本身是static):

auto a = make_lambda<0>();
auto b = make_lambda<1>();
std::cout << &a << ", " << a() << std::endl;
std::cout << &b << ", " << b() << std::endl;
Run Code Online (Sandbox Code Playgroud)

这不是您想要的语法,但是可以完成工作。如果您不介意涉及预处理器和潜在的编译器扩展,则可以使用帮助程序宏获取简单的函数调用语法。

#define make_lambda() make_lambda<__COUNTER__>()
Run Code Online (Sandbox Code Playgroud)

__COUNTER__GCC扩展名在哪里,每次在任何单个TU中需要扩展时,它都会扩展到新的号码。

  • @Quentin-我发誓C ++有很多我从未使用过的尘土飞扬的工具,然后发生了。 (3认同)
  • 然后,您手上就有一个*非常*神奇的bug,仅当两个调用在翻译单元之间完全对齐时才会破坏数据;)-编辑:哇,那是__COUNTER__,而不是__LINE__`神奇的少了一点,但仍然相当有问题的。 (2认同)