Size: a a a

2020 August 27

ПК

Побитый Кирпич... in pro.cxx
Было бы логичнее заставить полностью описывать концепт чтоб он покрывал всё тело
источник

Rn

Roman na in pro.cxx
Roman na
Есть. Я написал об этом. Не важно, что написано в методичках. Там чистейший динамический полиморфизм. Но в связи с тем, что язык как бы статический, да и на базе llvm - там нужна монорфизация, которую и впили в бекенд. Это ничего не значит. На уровне языка, его системы типов - полиморфизм динамический
Из статического - там существует отдельный вывод поверх сигнатур на генериках, для чего и нужен отдельный синтаксис. Но это к делу не относится
источник

Rn

Roman na in pro.cxx
Побитый Кирпич
Дак если ты не укажешь в концепте метод класса, но вызовешь его внутри функции, то получается, что ты обманул вызывающего и вместо Foo концепта ты принимаешь FooAndBar, но вызывающий об этом никак не узнает пока не получит ошибку.
Почему же обманул? Ты описал требования к типу. Если тип им удовлетворяет - он им удовлетворяет. В С++ это больше нужно для ограничения полиморфизма шаблонов. На этом не построен тайпчекинг, как в тех же генериках
источник

ПК

Побитый Кирпич... in pro.cxx
Roman na
Почему же обманул? Ты описал требования к типу. Если тип им удовлетворяет - он им удовлетворяет. В С++ это больше нужно для ограничения полиморфизма шаблонов. На этом не построен тайпчекинг, как в тех же генериках
Ну ты описал требования к типу, но потом вызвал у этого типа метод которого там не было. Получается теперь твои требования это не достаточное условие для вызова функции
источник

Rn

Roman na in pro.cxx
Побитый Кирпич
Было бы логичнее заставить полностью описывать концепт чтоб он покрывал всё тело
Нет. Зачем тебе покрывать всё тело, если оно и так тайпчекается? Тебе нужен конценпт, который ты хочешь вынести тайпчекинг в сфинае-контекст, либо задиспатчить свои типы по нескольким шаблонам
источник

m

magras in pro.cxx
Roman na
Есть. Я написал об этом. Не важно, что написано в методичках. Там чистейший динамический полиморфизм. Но в связи с тем, что язык как бы статический, да и на базе llvm - там нужна монорфизация, которую и впили в бекенд. Это ничего не значит. На уровне языка, его системы типов - полиморфизм динамический
Я не достаточно просвещен для того чтобы сказать, что точно понял. Поэтому попробую перевести на свой язык.

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

Rn

Roman na in pro.cxx
Побитый Кирпич
Ну ты описал требования к типу, но потом вызвал у этого типа метод которого там не было. Получается теперь твои требования это не достаточное условие для вызова функции
Не, это уже идеология которая была накручена поверх. В реальности в динамическом полиморфизме ты НЕ МОЖЕШЬ использовать то, что не описано в таблицы. А далее уже это обросло всякими ахренительными историями про "условия", "достаточно" и прочее. Зачем всё это?
источник

ПК

Побитый Кирпич... in pro.cxx
Roman na
Нет. Зачем тебе покрывать всё тело, если оно и так тайпчекается? Тебе нужен конценпт, который ты хочешь вынести тайпчекинг в сфинае-контекст, либо задиспатчить свои типы по нескольким шаблонам
Это только одно из применений. Есть ещё хотелка получить понятную ошибку компиляции, что у моего типа нет метода, а не обычную ошибку в шаблоне, где если не повезёт можно и не разобраться
источник

ПК

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

Rn

Roman na in pro.cxx
magras
Я не достаточно просвещен для того чтобы сказать, что точно понял. Поэтому попробую перевести на свой язык.

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

Rn

Roman na in pro.cxx
Побитый Кирпич
Это только одно из применений. Есть ещё хотелка получить понятную ошибку компиляции, что у моего типа нет метода, а не обычную ошибку в шаблоне, где если не повезёт можно и не разобраться
Наоборот, ошибки выводимые подобной системой наиболее непонятны и запутаны. Мы получаем ошибку не там, где должны. При этом концепты этому никак особо не помогают. Ошибка там генерируется такая же, просто немного места поменяны.
источник

Rn

Roman na in pro.cxx
Побитый Кирпич
Это только одно из применений. Есть ещё хотелка получить понятную ошибку компиляции, что у моего типа нет метода, а не обычную ошибку в шаблоне, где если не повезёт можно и не разобраться
Проблема в ошибках в С++ не в том, что они ошибки. А в том, что многие вещи достигаются путём всяких хаков, условно. Вот есть у тебя enable_if, который там что-то чекает и ошибка появится у тебя где-то непонятно где
источник

Rn

Roman na in pro.cxx
и вот у тебя теперь есть requires, который отвалится не в кишках enable_if и прочих костыльных трейтах/сфинае-хаках для доставания свойств типов.
источник

Rn

Roman na in pro.cxx
сделать красивые ошибки можно и сейчас - тем же статик-ассертом, но он пробивает сфинае.
источник

Rn

Roman na in pro.cxx
в концептах они будут куда более страшные. Разница в том, что ранее ты доставал условный begin хаком, который вывалил бы тебе свои кишки. Сейчас ты пишешь requires { begin(); } - который покажет тебе тот же самый трейс, что и обычная ошибка формирования, которая бы произошла в теле
источник

АК

Александр Караев... in pro.cxx
Roman na
в концептах они будут куда более страшные. Разница в том, что ранее ты доставал условный begin хаком, который вывалил бы тебе свои кишки. Сейчас ты пишешь requires { begin(); } - который покажет тебе тот же самый трейс, что и обычная ошибка формирования, которая бы произошла в теле
сейчас эти ошибки группируются в requires container_like_concept<T>, например, и ты видишь, что этот концепт провалился, потому что внутри него провалился другой концепт и т.д.
источник

Rn

Roman na in pro.cxx
только немного подход поменялся. В обычной ошибке тебе будет трейсить до ошибки и покажет ошибку. Это просто деталь реализации - можно сделать и иначе. А в requires тебе просто сначал сообщат "не смогла", а уже после дадут трейс и покажут почему
источник

Rn

Roman na in pro.cxx
Александр Караев
сейчас эти ошибки группируются в requires container_like_concept<T>, например, и ты видишь, что этот концепт провалился, потому что внутри него провалился другой концепт и т.д.
Это просто подход, как я писал выше. У тебя есть условный вызов функции - он известен. Далее этот вызов триггерит инстанцирование, который где-то отваливается на уровне тайпчека. Вот ты можешь показать как ошибку тот вызов/шаблон, который он пытался инстанцировать. Либо можешь показать место, где отвалился сам тайпчекинг.

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

Rn

Roman na in pro.cxx
ну и самое важное, ошибку концепта ты вообще никогда не должен мочь видеть. Если же ты её видишь - у тебя один шаблон и тебе хватит static_assert, который сгенерирует ошибки те, которые хочешь ты. Самые красивые
источник

Rn

Roman na in pro.cxx
улучшения там - это когда читаешь трейс компилятора с причинами отброса кандидатов
источник