Как стать автором
Обновить
30
-3
Тельнов Виктор @victor79

программист

Отправить сообщение
В том-то и дело, что в С++ лямбды не являются указателями. Они по значению передаются.

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


void sort(auto begin, auto end, const auto& compare)

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


Соответсвенно, вызов:


void sort(auto begin, auto end, auto compare)

Будет вести себя как при передаче по значению, для любого типа компаратора.


Лямбда на техническом уровне представляет структуру, с сохраненными в ней указателем на код и значениями замыкания (и это кажется было в стандарте). В случае передачи ее по ссылке, передается ссылка на эту техническую структуру. В случае передачи по значению — каждый раз она копируется.


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


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


Я по прежнему не понимаю, в чем проблемность типов описанных синтаксисом, что они принципиально отличаются от типов compile time.

Не совсем понятно, что такое косвенный и прямой вызовы относительно лямбд?


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


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

Вопрос, почему так изначально заложили? Почему нужно использовать костыль типа std::function, вместо того, что бы лямбды имели сразу подобные сигнатуры. Для этого были какие-то ограничения? Тип указателя на функцию замечательно работает и имеет определяемую сигнатуру независимо от значения. Чем не устроил тип указателя на лямбды по подобной же схеме? В момент появления стандарта про лямбды, до этого не было лямбд или чего-либо подобного, поэтому ограничений по обратной совместимости быть не должно было. Зачем было так все портить?


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

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


Ваш пример не оптимален для С++, поскольку не удобно поддерживать различные параметры вызова. std::function это шаблонная структура, как раз предком которой могла бы быть структура подобная Вашей.


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

Там нужно типа такого:


virtual void a(const std::function<void()>& fn);

При этом использование std::function действительно чуть медленнее, но не существенно. Основные тормоза буду, если будет void a(std::function<void()> fn), особенно при рекурсиях, т.к. объект std::function будет каждый раз конструироваться, и в довесок занимать лишние ~32 байта в стеке, против 8 байт, если передается по ссылке.

Конечно упс, Вы же в нее пихаете значение другого типа. Какой вопрос, такой и ответ. Если такое хотите, то юзайте параметр типа function<void()>.
    auto fn1 = []() { std::cout << 123 << std::endl; };
    using TT = decltype(fn1);

    struct A {
        virtual void a(TT fn) { fn(); }
    };

    struct B : public A {
        void a(TT fn) override { fn(); fn(); }
    };

    B a;
    a.a(fn1);
«Гений» и «идиот» это то же характеристики человека. Для меня, ИИ это чисто поиск корреляций и последущее их применение — математика, статистика, прогнозирование.
Любопытный момент, что ожидание от ИИ опасности, это исключительно животный рефлекс возникший в ходе эволюционной борьбы за выживание. И ровно так же ожидание, что ИИ будет ожидать опасность от человека, это наше предположение, что этот ИИ будет подобен людям — т.е. просто эмуляция и копирование человеческого поведения. Без многих милионов полоколений борящихся за выживание, эти опасения просто не будут иметь смысла. Любые опасения не будут иметь смысл.

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

А если исключить все ожидания человеческой рефлексности от ИИ, то там остается только ожидание полезности от ИИ, для всех или для какой-либо группы людей.
Верно мыслит. Только ему еще нужно уточнять, что эта опасность не от ИИ, а от людей это сделавших.
Скорость потребления соответствует логистическому распределению. И пока ресурсов в избытке, то скорость потребления растет темпами близкими к экспоненциальному. А потом бац, и экспонента скушала весь избыток ресурсов. Поэтому это утверждение одновременно и истинно и ложно. Но в эпоху ИИ будет экспоненциальный рост ресурсов. И любопотный вопрос, которая из экспонент победит? Пусть математики гадают.
Разум есть. Но этот разум, это просто один из механизмов человеческого восприятия. И лично я не вижу смысла притягивать этот механизм к реализации ИИ. Разные люди могут видеть разные определения в термине ИИ. Если рассматривать ИИ как эмуляцию поведения человека, тогда там имеет место быть разуму. Если рассматривать ИИ как помощника для человека для реализации его задач, то разум в этом случае это лишняя сущность.
Если у меня вдруг найдется финансирование или инвестирование, то я могу реализовать описанную мной тему. А пока без этого на это нет времени.
Везде пишут про GPT, но некоторые вещи можно и даже лучше делать без GPT. Периодически пишут, что GPT умеет делать новые программы, но программисты почему-то все еще нужны, и их не вытеснили генераторы программ на GPT. Ни разу не видел, что бы NLP на базе GPT могла вычислить простое сложение написанное на разговорном языке: «Сколько будет НЕКОЕ ЧИСЛО прибавить ДРУГОЕ ЧИСЛО?». Я конечно понимаю, что этому легко научить сетку, но этому легко научить, если этому ее специально учить. Но на все правила не сделать специальных подборок, а по произвольным подборкам, они такому не научиваются.
Ну да, компилится. Не приходилось использовать такой синтаксис. Тут чуть выше более простой вариант чем Ваш указывался.

Это не отменяет того, что я до этого написал.
Если Вы про макросы, то значит Вы не то увидели, что я хотел показать. Классический std::sort не принимает никаких указателей на поля. Я показал, какой должна быть функция сортировки, что бы туда можно было перечислить поля, без описания всего компаратора. В больших количествах сортировок по множеству полей, это очень утомительно прописывать, легко запутаться, что является источником ошибок.

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

Если Вы про что-то другое, то напишите полный пример. Незабудьте его проверить на компилируемость, а то, то что выше, не похоже на компилируемое.
Потому что пустой ссылка быть не может, такое не компилируется. Чуть ниже qw1 написал про это.
И на что будет ссылаться R& в случае не найденности? А если пользователь метода хочет использовать копирование для результата? Ссылки не переопределяются, и следовательно операторы копирования или перемещения работать не будут.

В любом случае, возврат ссылки будет не стабильным и не красивым для этого случая. Общеприменимая практика это возврат итератора.
Проблема не в макросах, проблема в головах. Одни любят придумать шаткие и сложнопонимаемые макросы — болезнь унаследованная от С. Другие видят эту болезнь в каждом макросе, и даже типовые #ifndef в хеадерах заменяют на #pragma once.

Одни могут и перочинным ножичком себя покалечить. Другие могут ходить с ружьем десятки лет, и не отстреливать себе ногу, но получая прибыль от этого большую, чем если бы ходили с перочинным ножиком.
Нужно возвращать итератор, т.е. тип decltype(list.begin()), и в случае не найденности list.end(). Если конечно не хотим копировать всю структуру строки в результат.

Или указатель на элемент списка, т.е. тип decltype(&*list.begin()), и в случае не найденности nullptr.

Информация

В рейтинге
Не участвует
Откуда
Санкт-Петербург, Санкт-Петербург и область, Россия
Зарегистрирован
Активность