Подтвердить что ты не робот

Поддерживает ли С++ 11 локальные функции?

Теперь, когда в С++ есть lambdas, кажется, что это глупо, что я не могу объявить локальную функцию...

например:.

Я могу объявить тип в теле функции, даже инициализировать его как таблицу значений. Но я не могу создать вспомогательную функцию, которая работает с этим типом данных, потому что я не могу объявить функцию в функции, и я не могу ссылаться на этот тип данных вне функции, потому что она доступна только в этой области.

Бывают случаи, когда довольно просто вытащить тип данных из функции и определить мой тип данных и вспомогательные функции там (область локального файла) - но бывают случаи, когда это действительно не правдоподобное решение - например, при инициализации таблицы встроенными lambdas, которые ссылаются на локальные переменные области (или это).

Любая идея о том, подходит ли поддержка для локальных функций, уже определена или почему их сложно реализовать разработчикам компилятора и, следовательно, не являются частью стандарта?

4b9b3361

Ответ 1

Нет локальных функций, но они не так полезны без закрытия, то есть доступ к локальным переменным. В любом случае вы можете легко эмулировать локальную функцию с лямбдой.

Вместо:

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 могут без проблем использовать локальные типы. Но, конечно, публичные статические функции-члены в этой структуре должны работать и отлично.

И как дополнительная заметка, косвенно связанная с вашим вопросом, разрешено в С++ 11 создавать экземпляр шаблона с использованием локального типа (это было запрещено в С++ 98):

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

Ответ 2

В С++ 11 нет локальных функций.

Но есть лямбды.

И ваш локальный тип может иметь функции-члены!

Ответ 3

Нет, вы не можете этого сделать, но, безусловно, лямбды более полезны, чем чистые локальные функции, поскольку они также могут захватить состояние? Они могут либо использоваться анонимно, либо присваиваться автоматической переменной и использоваться в любом количестве мест, как вам нравится.

Ранее другим основным решением (особенно при использовании стандартных библиотечных алгоритмов) было определение локальной структуры-функтора с подходящей реализацией operator(). Вы также можете захватить состояние, используя этот метод, но для этого требуется больше кода. Лямбдас - очень аккуратный и лаконичный способ достижения того же самого.

Ответ 4

Локальные функции, безусловно, не сложно реализовать, они присутствовали, по крайней мере, в 1968 году в Паскале, возможно, даже раньше. Они реализованы как расширение C в GCC.

Передача адреса вложенной функции несколько более сложна, обычно она включает в себя создание фрагмента кода (батут), который сначала настраивает статический канал/дисплей/любой механизм, используемый для доступа к локальным переменным, а затем выполняет фактический код функции. Батут находится в стеке, что означает, что стек должен быть исполняемым, с обычными последствиями для безопасности.

Независимо от того, рассмотрел ли комитет С++ и отклонил вложенные функции, кто-то догадывается, но я бы предположил, что, хотя это и не так сложно реализовать, преимущества вложенных функций на самом деле не стоят усилий.

Ответ 5

Это довольно запутанно, но вы можете создать локальную функцию внутри локального типа структуры:

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

Обратите внимание, что локальная функция не имеет доступа к локальным переменным - для этого вам понадобится лямбда. Однако это может быть полезно для локальных перегрузок:

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);
}