简体   繁体   English

在本地定义的结构中模拟非本地(或自由)变量

[英]Simulating non-local (or free) variables in a locally defined struct

This question probably only makes sense for people with knowledge on programming languages supporting closures. 这个问题可能只对了解支持闭包的编程语言的人有意义。 If you don't, please do not comment "why would you like to do this?": there are tons of legitimate reasons to do that. 如果您不这样做,请不要评论“您为什么要这样做?”:这样做有很多合理的理由。

It is common in functional languages to define local functions that capture the already defined local variables. 在函数式语言中,通常会定义捕获已定义的局部变量的局部函数。 In C++, that would look like (but of course is illegal): 在C ++中,这看起来像(当然是非法的):

#include <iostream>
using namespace std;

int main()
{
    int x = 0;
    int f() { return x + 1; }

    cout << f() << endl; // would print 1

    x = 2;
    cout << f() << endl; // would print 3
}

To allow this, C++11 introduces lambda functions , so it is actually possible to do it in a rather nice way (though, not as nice as it generally is in functional languages ;-) ): 为此,C ++ 11引入了lambda函数 ,因此实际上有可能以相当不错的方式做到这一点(尽管,它不像通常的函数式语言中那样好;-)):

#include <iostream>
using namespace std;

int main()
{
    int x = 0;
    auto f = [&] () { return x + 1; };

    cout << f() << endl; // actually compiles and prints 1

    x = 2;
    cout << f() << endl; // actually compiles and prints 3
}

My question is: now that it is possible to automatically capture free variables by reference for functions , wouldn't that be nice to be possible to do for locally defined structs ? 我的问题是:现在可以通过引用函数自动捕获自由变量了,这对于在本地定义的结构体上实现不是很好吗? Ideally, I would love to be able to write: 理想情况下,我希望能够写:

int main()
{
    int x = 0;

    struct A 
    {
        int y;
        A(int y) : y(y) {}

        int f() { return x + y; };
    };

    A a1(1);
    A a2(2);

    cout << a1.f() << endl; // would print 1
    cout << a2.f() << endl; // would print 2

    x = 2;
    cout << a1.f() << endl; // would print 3
    cout << a2.f() << endl; // would print 4
}

The only workaround I've found is to manually pass as argument to the constructor all the non-local (free) variables, which is a bit of a pain when there are plenty of them: 我发现的唯一解决方法是将所有非本地(免费)变量作为参数手动传递给构造函数,当有很多非本地变量时,这会有些麻烦:

#include <iostream>
using namespace std;

int main()
{
    int x = 0;

    struct A 
    {
        // meaningful members
        int y;
        int f() { return x + y; };

        // free variables
        int & x;

        // Constructor
        A(
            // meaningful arguments
            int y,

            // capturing free variables
            int & x

        ) : y(y), x(x) {}
    };

    A a1(1, x);
    A a2(2, x);

    cout << a1.f() << endl; // prints 1
    cout << a2.f() << endl; // prints 2

    x = 2;
    cout << a1.f() << endl; // prints 3
    cout << a2.f() << endl; // prints 4
}

Do you know of any other workaround that would avoid manually passing as argument all free variables, or do you know if these kind of "environment-aware" locally-defined structs are considered for future extensions of C++? 您是否知道可以避免手动将所有自由变量作为参数传递的任何其他解决方法,或者您是否知道在将来的C ++扩展中是否考虑使用这类“环境感知”的本地定义结构? (ie, C++1y?) (即C ++ 1y?)

What you ask for is not available, but you can get similar results by combining functions with a combination of lambdas and binders: 您所要求的不是可用的,但是通过将函数与lambda和粘合剂结合使用,您可以获得类似的结果:

auto lambda = [](int i) { return x+i; };
auto a1 = std::bind(lambda,1);
auto a2 = std::bind(lambda,2);

Depending on the amount and shape of changes, you could invert the solution and have a struct that takes the lambda with the capture and then adds it's own logic. 根据更改的数量和形状,您可以反转解决方案,并具有一个结构,该结构将lambda与捕获一起添加,然后添加其自己的逻辑。

I don't find this particularly beautiful, and I'm not entirely sure it's compliant, but neither g++ nor clang++ complains about this: 我觉得这不是特别漂亮,我也不完全确定它是否兼容,但是g ++和clang ++都没有抱怨:

#include <iostream>

int main()
{
    int x = 1;

    auto l = [&](int p){
        auto ll0 = [&, p]{ return p + x + 5; };
        auto ll1 = [&, p]{ return p + x * 2; };

        struct
        {
            decltype(ll0) l0;
            decltype(ll1) l1;
        } ret{ll0, ll1};

        return ret;
    };

    std::cout << l(42).l0() << '\n';

    auto lo = l(21);
    std::cout << lo.l1() << '\n';
}

I think the creation of the unnamed struct could possibly be automated by a macro. 我认为未命名结构的创建可以通过宏自动进行。

The lambda expressions of C++ are the capturing mechanism and inline object literals of a sort. C ++的lambda表达式是一种捕获机制和内联对象文字。 Depending on your exact purpose, they may be more convenient than a local struct definition. 根据您的确切目的,它们可能比本地结构定义更方便。

As a motivating example, consider the following: 作为一个激励示例,请考虑以下内容:

// environment
int offset = 42;

struct local_type {
    // capture environment 'by-hand'
    int offset;

    // purpose of the local type is to expose two overloads
    int operator()(int x) const
    { return x + offset; }

    double operator()(double x) const
    { return x + offset; }
} f { offset };

You can turn this on its head by doing: 您可以这样做:

int offset = 42;
auto f = make_overload([=](int x) { return offset + x; },
                       [=](double x) { return offset + x; });

The lambda expressions take care of capturing, the make_overload combinator takes care of building the desired object -- here, one that has an overloaded operator() . Lambda表达式负责捕获, make_overload组合器负责构建所需的对象-在这里,该对象具有重载的operator() (It would be implemented best by making use of inheritance.) (最好利用继承来实现。)

This approach makes sense if you know that you'll (re)use make_overload from various places. 如果您知道要从各个地方(重新)使用make_overload ,则此方法很有意义。 For one-time, special uses there's no avoiding writing a specialty type, whether local or not. 一次,特殊用途不可避免地要编写特殊类型,无论是否为本地。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果全局 function 使用非局部变量是否正确,那么它是一个闭包? - Is it correct that if a global function uses non-local variables, then it's a closure? 在 C++ 中,哪些链接被授予非局部成员变量? - Which linkages are granted to non-local member variables in c++? 静态和动态初始化仅适用于非局部变量吗? - Do static and dynamic initialization only apply to non-local variables? 非局部非内联变量的初始化:它是否严格在调用main()函数之前进行? - The initialization of non-local non-inline variables: does it take place strictly before the `main()` function call? 非本地函数调用本地类型 - non-local function call local type 甚至在执行 `main()` 的第一行之前就出现分段错误,并且没有非局部变量 - Segmentation Fault before even the first line of `main()` is executed and there are no non-local variables 在不同的翻译单元中对带有静态存储持续时间的相关非局部常量浮点变量进行常量初始化 - Constant initialization of dependent non-local constant float variables w/ static storage duration in different translation units 关于非本地静态变量初始化的规则是什么? - What are the rules regarding initialization of non-local statics? 非局部变量的动态初始化是线程安全的吗 - Is the dynamic initialization of the non-local variable thread-safe 非本地变量在C ++中使用匿名类型警告 - non-local variable uses anonymous type warning in C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM