Как стать автором
Обновить
85
0.6
Евгений Охотников @eao197

Велосипедостроитель, программист-камикадзе

Отправить сообщение

Вот так для вас достаточно наглядно: https://wandbox.org/permlink/fPZtYE5VtpKvWc9l
?

Можете еще обратить внимание, что f и g принимают аргументы по-разному.

А общего ответа нет.

А вот представляете, в том, что воплощено в жизнь в C++, этот общий ответ таки есть! Невероятно для вас, не так ли?

А размещение на стеке без копирования куда-либо оказывается всего лишь приятным следствием оптимизации.

Вот ведь какая реальность. Сурово она с вами.

Я ж вам написал – в памяти, предоставленной функцией, вычислившей значение лямбда-выражения.

Это тот же самый стек. Который не применим, если лямбда должна пережить вызов создавшей её функции.

Более поучительно рассмотреть такой пример.

Я вам привел более поучительный пример выше с использованием копирования лямбд и хранения их в контейнере. Вы явно его не поняли. Разберитесь сперва с ним.

Например, стек.

Например не катит, хватит уже строить из себя великого теоретика. Лямбда в C++ может быть вызвана несколько раз. Где именно будет храниться ее состояние между вызовами? Стек не подойдет в общем случае.

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

Ой, какие эпитеты, какая патетика.

Те, кто нормально программируют на C++ (а не строят из себя самого умного в комментариях на Хабре) постоянно извлекают полезную пользу из того факта, что лямбда в C++ -- это функтор.

Речь идёт о том, что эти класс и объект не являются ни концептуально, ни технически необходимыми.

Это уже разговоры о том, что и как могло бы быть у бабушки, чтобы это была уже не бабушка, а скорее дедушка. Но в C++ сделали именно так, получилось и просто, и понятно, и удобно (по крайней мере по меркам C++).

Весь их смысл состоит в том, чтобы соответствовать парадигме C++ “всё есть объект”

Еще раз попрошу координаты вашего дилера. Уж очень крутые вещества он вам поставляет. В C++ нет такой парадигмы.

Если захватывается только значение переменной, а не она сама (т.е. не ссылка на неё), то это значение будет храниться в локальной памяти функции.

А что такое "локальная память" функции? Стек?

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

А если так: https://wandbox.org/permlink/AX8YzQKz7xsmHYXF

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

Да что же вы такое несете?

https://wandbox.org/permlink/PHtTWQypppHytz0r

Здесь c в лямбде захвачено по значению. И c из лямбды должно где-то хранится.

Если это описание объекта ООП

Это не описание объекта ООП. Это описание того, что получается в результате работы компилятора. А получается объект. К которому применимы некоторые признаки ООП. А посему термин "инстанс" здесь вполне уместен, но именно что в смысле "экземпляр". Поэтому когда вы лезете в разговор о C++ со своим абстрактным "инстансом", то это вызывает недоумение и просьбы уточнить что вы имеете в виду.

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

А почему бы им не использоваться в шаблонах?

Потому что в шаблонах используются не "выражения", а типы или значения. А вот этот вот ваше "лексическое" определение лямбды в виде [...](...){...} ничего на сей счет не говорит.

В отличии от.

Здесь “an unnamed function object capable of capturing variables in scope” – это и есть просто определение closure.

Как по мне, так это не определение closure, это описание того, что создается в результате обработки лямбда выражения компилятором C++. А именно -- функциональный объект. Который может быть замыканием, а может и не быть.

Так ничего, кроме синтаксиса, по самому большому счёту и не нужно.

Не нужно для чего? Если для того, чтобы продемонстрировать свою банальную эрудицию в сраче на Хабре, то да, больше ничего не нужно.

Если для того, чтобы без проблем пользоваться лямбдами в C++, то это только-только самое начало. Поскольку синтаксис ничего не говорит о том, почему же тогда лямбды могут использоваться в шаблонах. Вроде:

template<typename L> void f(L &&l) {...}

и какой смысл здесь играет "universal reference".

Или вот такое:

std::unique_ptr<ExtType, decltype([](ExtType * p) { freeResource(p); })> holder{...};

Вот уважаемый @qw1 уже изучил теорию

Он изучил то, чего раньше не знал. Я специально лямбда-исчисление не изучал, но наслышан. И это одна из причин почему я вынужден снова и снова макать вас в известную субстанцию и повторять: речь идет о лямбдах в C++, о сугубо практических вещах, перестаньте натягивать на глобус какую-то абстрактную теорию.

А всякие классы и объекты – это просто детали реализации.

Ну ёжкинжеж... Гладко было на бумаге, да, как известно что забыли.

Из этого многообразия у меня ничего не называется “инстанс”.

Тогда что такое "инстанс"?

"Имя, сестра! Имя!" (с)

Этот вопрос не имеет отношения к ООП.

И то хорошо.

Я вроде понял, о чём он говорит.

Скорее всего вы правы.

Здесь – это в определении термина closure, которое вы процитировали.

Я не цитировал определение closure, не приписывайте мне того, чего я не говорил.

И если речь идет про замыкание, то это и есть та часть "сахара", который дает программисту C++ный компилятор. Во времена C++98 функторы приходилось делать вручную и замыкание можно было соорудить на обычных классах только врукопашную, поэтому речь о closure и не шло. Теперь компилятор позволяет это сделать.

Никакой “лямбды” в C++ нет.

Ну надо же. Ж есть, а слова нет.

Есть лямбда-выражение, и это ни что иное, как именно выражение ... {...}.

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

А есть ООП-шный объект, который порождается от безымянного класса и является значением лямбда-выражения.

О, надо же, до вас дошло.

И ещё есть результат применения функтора, являющегося значением лямбда-выражения, к конкретному списку фактических параметров.

А есть еще и само по себе "применение функтора", т.е. вызов operator(), который может занимать какое-то время и приводить к разным результатам.

И, проблема в общении с вами в том, что вы не можете вменяемо обозначить что из всего этого многообразия у вас называется "инстанс".

Но роль лямбда-выражения не сводится только к генерации функтора, она ещё и лексическая.

Лексическая роль пусть волнует разработчиков компиляторов, статических анализаторов и IDE. Мне, как простому пользователю языка, интересно то, чем лямбда является в итоге.

Не-не. Здесь речь идёт об определении closure, и имеется в виду список захвата, который как раз и требует применения лексического замыкания.

Здесь -- это где?

Лексическое замыкание делается компилятором. Но, при этом, в C++ оно так же специфическое, т.к. программист должен явным образом описывать что же именно (и как именно) он хочет "замкнуть".

Ну и добавим сюда, что в C++ лямбда может "замкнуть" не только что-то из объемлющего контекста, но и определить собственные "члены" в виде новых объектов, доступных только внутри лямбды (но не локальные переменные в теле лямбды). Вроде вот такого:

int make_value() {...}

auto l = [v = make_value()]() { ... };

Вот только к экземпляру класса (объекту в смысле ООП) это не имеет никакого отношения, а является поведением функционального объекта в смысле

Еще раз: в C++ лямбда -- это экземпляр анонимного класса. Список захвата трансформируется в поля этого класса. Грубо говоря:

int a = ...;
auto l = [a]() {...};

есть ни что иное как:

class __autogenerated_lambda_1 {
  int a;
public:
  __autogenerated_lambda_1(int a_initial) : a{a_initial} {}
  auto operator()() { ... /* здесь имеем дело с __autogenerated_lambda_1::a */ }
};
...
int a = ...;
__autogenerated_lambda_1 l{a};

И как раз этот автоматически сгенерированный функтор и есть вполне себе нормальный ООП-шный объект (при условии, что вам достаточно только инкапсуляции из ООП-шной триады).

является поведением функционального объекта в смысле функционального программирования, которое в C++ целиком реализуется на этапе компиляции

Поделитесь контактами поставщика вашей дури. Аж завидно.

В смысле инкапсуляции. Что есть один из трех "китов" ООП.

Если для вас непонятно, то речь идет о том, что в функциональном объекте есть свои члены, которые доступны из operator():

class functor_demo {
  int a_;
  int b_;
public:
  functor_demo(int a, int b) : a_{a}, b_{b} {}
  void operator()() { a_ += 1; b_ += 2; }
  int dummy() const { return a_ + b_; }
};

functor_demo fo{1, 2};

К содержимому fo.a_ и fo.b_ вы снаружи просто так не доберетесь. Что и есть инкапсуляция.

Ну ёжкинжеж...

В C++ уже давным давно есть устоявшийся термин "function object" (он же функтор -- functor). Вы его можете найти на том же cppreference. Или, например, здесь.

И да, ссылка на Wiki там сделана не для function object-а, а для closure.

Тот факт, что вы отрицаете применимость ООП к C++ными функторам... Ну тут у вас либо опять "горе от ума", либо вообще дефицит этого самого ума.

Ну откройте стандарт или любое описание C++, там будет конкретно написано, что такое лямбда-выражение.

Вы тут уже пытались блеснуть цитатой:

[ captures ] front-attr (optional) (params ) specs (optional)exception (optional)
back-attr (optional) trailing-type (optional) requires (optional){ body }

Только вот это относится лишь к синтаксису описания лямбды.

Ну и, например, первая же строчка описания lambda-expression на cppreference.com говорит:

Constructs a closure: an unnamed function object capable of capturing variables in scope.

Вы здесь просто путаете лямбда-выражение с его значением.

В теории.

На практике вы путаете теорию (возможно ведомую только лично вам) с практикой языка C++.

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

Еще раз вам повторю: лямбда в C++ -- это инстанс (т.е. экземпляр, т.е. объект) некоторого автоматически сгенерированного анонимного класса.

Поэтому с точки зрения C++ это ваше заумное "лямбда-выражение в контексте его вызова" -- это вообще что-то странное. Поскольку есть а) экземпляр лямбды и b) есть конкретный вызов лямбды (т.е. вызов operator() у экземпляра лямбды). И вот ХЗ что вы под "инстансом" понимаете.

У вас основная проблема в том

Или в том, что взялся что-то объяснять вам.

Видите, вы сами интуитивно понимаете, о чём идёт речь.

Еще раз, для людей с проблемами развития и пониженной социальной ответственностью: вы используете термин "инстанс", у вас спрашивают что вы под этим понимаете, вы не можете дать вменяемое описание вашего использования термин "инстанс".

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

Тьфу, срамота.

а стек-фрейма может и вообще не быть.

А вы допустите. Типа "в случае традиционной реализации на стековой архитектуре это будет вызов со своим конкретным стековым фреймом". Этого могло бы быть достаточно.

Но, так понимаю, проста изложения мыслей и вы проживаете в разных вселенных.

Я отвечаю на конкретные обращённые ко мне вопросы.

Т.е. вышли позвизд покичиться своей ученостью?

Вот вы неугомонный какой.

А вы не блудите мыслею по древу.

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

Вы дали ссылку на Wiki, в которой термин instance использовался для обозначения двух разных вещей. Так что от вас ожидалось хотя бы объяснение в каком именно смысле вы здесь, в этом обсуждении используете "инстанс". Но вы не смогли.

В философском понимании, инстанс – это онтологический бытийный статус какой-либо сущности. Полегчает нам от этого в техническом смысле?

Вам -- не знаю. Для меня это еще одно доказательство того, что у вас с головой нелады. Ибо в данном разговоре достаточно определить "инстанс" -- это синоним экземпляра/объекта (типа "инстанс класса D" как "объект класса D") или же это "конкретный вызов конкретной функции в конкретным фрейм-стеком и конкретными значениями переданных параметров". Или же еще что-то.

Если вы не можете разговаривать на таком уровне, то я мог бы сказать, куда свою ученость вы могли бы засунуть из-за ее полной бесполезности. Но, боюсь, на Хабре не принято в прямой разговор.

И это нормально, особенно в молодости.

Конечно, и только вы с высоты своих лет познали истину.

Поэтому локальная переменная в теле метода класса, безусловно, является частью класса.

Ну да, ну да.

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

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

Я человек педантичный и люблю правильное использование терминологии.

Но при этом не можете в ходе дискуссии сформулировать определение используемого вами же термина "инстанс".

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

И какой практический смысл в обсуждении "фундаментальных вопросов" в комментариях к сугубо утилитарной статье?

Если вы считаете, что в C++ используется какая-то "неправильная" терминология, а C++ники намеренно искажают какие-то устоявшиеся в некоторой теории понятия, то напишите статью с изложением вашей точки зрения и ссылками на работы, в которых эти самые "термины" и "понятия" вводятся.

Может от этого будет больше пользы.

Здесь же вы пока договорились лишь до того, что локальная переменная в теле метода класса является частью класса. Если "фундаментальные вопросы" в вашем понимании ведут к такому маразму, то может ну их вообще?

Является, конечно

Простите, с этого момента я пас.

И что из этого?

А то, что вы не определили смысл своего "инстанс" и говорить "мы в итоге договорились о терминологии" преждевременно.

Информация

В рейтинге
1 538-й
Откуда
Гомель, Гомельская обл., Беларусь
Зарегистрирован
Активность