C ++ 11是否支持本地功能?

时间:2011-11-09 19:58:24

标签: c++ c++11

现在C ++中有lambdas,我无法声明本地函数似乎真的很傻......

e.g:

我可以在函数体中声明一个类型,甚至可以将其初始化为值表。但我无法创建一个与该数据类型一起使用的辅助函数 - 因为我无法在函数中声明函数,并且我不能在函数外部引用该数据类型,因为它仅在该范围内可用。

有时候将数据类型拉出函数非常简单,并在那里定义我的数据类型和辅助函数(本地文件范围) - 但有时候它并不是真正合理的解决方案 - 例如使用引用局部范围变量(或者这个)的内联lambda初始化表时。

是否已经定义了对本地函数的支持是否已经定义,或者为什么编译器编写者难以实现它们,因此它们不是标准的一部分?

5 个答案:

答案 0 :(得分:24)

没有本地函数,但如果没有闭包,它们就没那么有用,也就是访问局部变量。在任何情况下,您都可以使用lambda模拟一个本地函数。

而不是:

void foo(int x)
{
    struct S
    {
         //...
    };
    int Twice(int n, S *s) //Not allowed
    {
        return 2*n;
    }

    S s;
    int x = Twice(3, &s);
    //...
}

执行:

void foo()
{
    struct S
    {
         //...
    };
    auto Twice = [](int x, S *s) -> int //Cool!
    {
        return 2*x;
    }; //Twice is actually a variable, so don't forget the ;


    S s;
    int x = Twice(3, &s);
    //...
}

如果捕获集为空,([])它甚至可以转换为普通的指向函数的指针,就像真正的指针一样!

AFAIK,lambdas可以毫无困难地使用本地类型。但是,当然,该结构中的公共静态成员函数也可以正常工作。

作为另外一个与您的问题间接相关的注释,C ++ 11中允许的是使用本地类型(在C ++ 98中禁止)实例化模板:

void foo()
{
    struct S {};
    std::vector<S> vs; //error in C++98, ok in C++11
}

答案 1 :(得分:9)

C ++ 11中没有本地函数。

但是有lambdas。

您的本地类型可以具有成员函数!

答案 2 :(得分:3)

不,你不能这样做但是lambdas肯定比纯本地函数更有用,因为它们也可以选择捕获状态吗?它们既可以匿名使用,也可以分配给自动变量,并可以在任意多处使用。

以前,其他主要的解决方法(特别是在使用标准库算法时)是使用合适的operator()实现来定义本地functor结构。您还可以使用此方法捕获状态,但需要更多代码才能执行此操作。 Lambdas是一种非常简洁的方式来实现同样的目标。

答案 3 :(得分:1)

本地功能绝对不难实现,它们至少在1968年出现在Pascal中,甚至更早。它们在GCC中作为C扩展实现。

传递嵌套函数的地址有点复杂,它通常包括设置一段代码(trampoline),它首先设置静态链接/显示/用于访问局部变量的任何机制然后执行实际功能代码。 trampoline驻留在堆栈上,这意味着堆栈必须是可执行的,具有通常的安全隐患。

C ++委员会是否已考虑并拒绝嵌套函数是任何人的猜测,但我建议,虽然 难以实现,但嵌套函数的好处并不值得付出努力。< / p>

答案 4 :(得分:1)

它相当复杂,但您可以在本地结构类型中创建一个本地函数:

int quadruple(int x) {
  struct Local {
    static int twice(int val) { return val * 2; }
  };
  return Local::twice(Local::twice(x));
}

请注意,本地函数无法访问局部变量 - 您需要一个lambda。但是,它对本地重载很有用:

template <typename T>
T mod(T x, T y) {
  struct Local {
    static int local(int x, int y) { return x % y; }
    static double local(double x, double y) { return std::fmod(x, y); }
  };
  return Local::local(x, y);
}