Хорошо, сначала давайте разберем, что делает ваш JavaScript.
function()
{
var id = 0;
return function() { return id++; };
}
Это создает функцию.Функция без имени, которая не принимает параметров.Эта функция при вызове вернет новую функцию.Внутренняя функция будет иметь доступ к переменной локальной области видимости, и эта переменная будет частью состояния этой внутренней функции.
Каждый раз, когда эта функция вызывается, она возвращает new функция.Эта новая функция будет иметь свое собственное состояние (в конце концов, var id = 0;
должен что-то делать).Каждый вызов внешней функции будет возвращать новую функцию с новым состоянием.
This:
(function()
{
var id = 0;
return function() { return id++; };
})
Заключает функцию в пару круглых скобок.Это необходимо для правил приоритета операторов, чтобы это работало:
(function()
{
var id = 0;
return function() { return id++; };
})()
Это создает функцию, а затем вызывает функцию.Это то, что последний ()
делает в конце.Он вызывает внешнюю функцию, которая создает внутреннюю функцию с собственной областью действия и возвращает ее.
В этом выражении внешняя функция теряется .Это ушло;Вы не можете получить к нему доступ больше.Вы создали его достаточно долго, чтобы вызвать его, а затем позволили ему упасть в мусорную корзину для сборки мусора.
Учитывая все это, мы можем видеть, что это утверждение:
var uniqueID1 = (function()
{
var id = 0;
return function() { return id++; };
})();
Создаетвнешняя функция вызывает функцию, которая возвращает новую функцию, а затем сохраняет функцию inner в переменной с именем uniqueID1
.
Если вам нужно доказать, что это правда, попробуйте этов вашем HTML:
var uniqueMaker = function()
{
var id = 0;
return function() { return id++; };
};
var uniqueID1 = uniqueMaker();
var uniqueID2 = uniqueMaker();
Вы получите тот же ответ, что и в вашей версии для копирования и вставки.
Если мы хотим, чтобы код C ++ имитировал это, нам нужно выполнить каждый шагс правильным кодом C ++.
Во-первых, внутренняя функция.В C ++ лексическая область видимости не существует.Поэтому вы не можете возвращать функции, которые ссылаются на переменные в других областях.Вы можете вернуть только лямбду, у которой есть копия переменных из другой области видимости.Кроме того, лямбды не могут изменять область, если вы явно не разрешаете это.Таким образом, внутренний код должен выглядеть так:
int id = 0;
return [=]() mutable { return ++id; };
Это все хорошо, но теперь нам нужно создать лямбду, которая будет возвращать эту лямбда-функцию с состоянием.В C ++ функции, которые имеют состояние, не совпадают с указателями на функции.А поскольку тип лямбды определяется компилятором, нет способа набрать его имя.Поэтому мы должны использовать std::function
в качестве возвращаемого типа внешней функции.
[]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
}
Это создает лямбда-функцию, которая при вызове возвращает внутреннюю функцию со своим собственным состоянием.Состояние, которое не зависит от любых последующих вызовов этой функции.Как в примере с JavaScript.
Теперь этого недостаточно.Помните, ваш JavaScript создает внешнюю функцию, вызывает ее и сохраняет only ее возвращаемое значение.Сама внешняя функция отбрасывается.Таким образом, мы должны подражать этому.К счастью, это достаточно просто в C ++;он выглядит так же, как JavaScript:
([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})()
Наконец, мы помещаем его в переменную:
auto uniqueID1 = ([]() -> std::function<int()>
{
int x = 0;
return [=]() mutable { return x++; };
})();
Тип uniqueID1
будет std::function<int()>
.Это не будет тип внешней функции.Внешняя функция - это просто временная функция, которая использовалась для создания внутренней области видимости.