cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

Добавить возможность вычисления дэфолтных аргументов в месте вызова. #501

Open sergii-rybin-tfs opened 2 years ago

sergii-rybin-tfs commented 2 years ago

Сейчас дефолтные аргументы для функций вычисляются в месте объявления.

Дополнительно к этому механизму я предлагаю добавить механизм для вычисления дефолтных аргуметнов в месте вызова.

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

Вообще же горизонты применения этого функционала гораздо шире логирования. Можно запрещать или разрешать вызов API из определенных неймспейсов или классов (нечто наподобии инкапсуляции для функций). Можно специализировать поведение функций в зависимости от места вызова (например в singleThread нэймспейсе одно поведение, а в multithread другое, а в классе где есть mutable mutex c определенным именем - третье, а в юнит тестах - четвертое).

Говоря языком паттернов, можно делать mixin`ы на функциях.

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

Красивый синтаксис (и главное простой и выразительный) я не придумал, он может быть чем то наподобии:

int log( const string &context = declevaluate( getContext() ), const string & line = declevaluate( __LINE__) , const string & var );
oficsu commented 2 years ago

Сейчас этот механизм реализуется через макрофункции (что не удобно)

Это, конечно же, не обязательно так

Можно запрещать или разрешать вызов API из определенных неймспейсов или классов

Из классов давно возможно разрешать или запрещать, реализуется через Passkey Idiom

будет с удивительными возможностями многие из которых еще предстоит открыть

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

sergii-rybin-tfs commented 2 years ago

Это, конечно же, не обязательно так

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

Из классов давно возможно разрешать или запрещать, реализуется через Passkey Idiom

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

do( /* something */, context );
draw( /* something */, handle );
allocate( /* something */, allocator );
log( /* something */, classname );
dispatch( /* something */, tag );
invoke( /* somethign */, singletonAddr );

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

Дефолтные параметры уже сами по себе активно используются для уменьшения шума в коде. А вычисляемые дефолтные параметры, могут быть еще более полезными. Их архитектура хорошо ложится на сущности с которыми приходится работать мозгу. Функции принеси_это(), заработай_денег(), пошли_спать(), это всё у нас в мозгу имеют дефолтный и иерархический контекст который зависит от места\времени\страны\воспитания итд. У нас появится много новых паттернов для выражения статического полиморфизма, параметризированного не типом, а местом (контекстом) вызова функции.

AndreyG commented 2 years ago

Сейчас дефолтные аргументы для функций вычисляются в месте объявления.

Нет, они вычисляются в месте вызова, а резолвятся в месте объявления. Вы же предлагаете их резолвить в месте вызова. При этом почти во всех ваших примерах значение по умолчанию это просто qualified-reference. А ведь это может быть выражение произвольной сложности. Отложено резолвить eго звучит довольно безумно.