Есть ли в C ++ 11 поддержка локальных функций? - PullRequest
24 голосов
/ 09 ноября 2011

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

например:

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

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

Ответы [ 5 ]

24 голосов
/ 10 ноября 2011

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

Вместо:

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

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

Do:

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

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

void foo()
{
    struct S {};
    std::vector<S> vs; //error in C++98, ok in C++11
}
9 голосов
/ 10 ноября 2011

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

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

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

3 голосов
/ 10 ноября 2011

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

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

1 голос
/ 04 декабря 2014

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

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);
}
1 голос
/ 10 ноября 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...