У меня нет проблем с тем, что стандарт добавляет новые методы в код, которым владеет стандарт (то есть, в стандартную библиотеку). Но лично меня немного смутило бы, если бы стандарт добавил новые методы в код, которым владею я. А вас?
так пользовательский код зависит от стандартного... вот например в с++20 добавили std::string::starts_with, а значит поменялся пользовательский код, диспатчащий по наличию T::starts_with. Значит ли это, что метод не стоило добавлять?
Нет. <сниппет> счастливо вам даст жёсткую ошибку, а не return false;
А зачем его обходить? Поменяли бы поведение, мы ж уже выяснили, что это не проблема. Так бы заодно и начинающим удобнее было.
то, что вы где-то у себя выяснили, всё еще имеет весьма опосредственное и натянутое отношение к действительности.
Да нет, очень просто: новые синтаксические конструкции SFINAE добавлять не мешает
а изменения нужны, и не только посредством новых синтаксических конструкций. Вы очень старательно упускаете тот нюанс что в с++17 S(1) не компилировался.
Эти три вещи несовместны, одну придётся вычеркнуть.
хорошо, одну вещь я таки наконец-то доказал, аллелуйа. Теперь осталось доказать что доля кода, поведение которого зависит от компилируемости будущих синтаксических конструкций, ничтожно мала, и вы будете еще на шаг ближе к пониманию истины.
Скажите, наконец, что C++ более не заботится о сохранении семантики программы при апгрейде, и не будет ни у кого никаких вопросов, в конце концов.
я утверждаю, что с++ обеспечивает тот уровень обратной совместимости, который можно сохранить попутно обновляя язык.
Я не готов обсуждать аксиоматику с таким уровнем формализма.
Очевидно, что нет. SFINAE не проверяет тела функций, например, и ошибка в теле функции даже в SFINAE-контексте (или какой там правильный термин) будет hard error.
SFINAE проверяет ровно то, что передали в контекст подстановки. Если в этом контексте есть ошибка - подстановка провалится.
MVP работает только для академических языков. Для языков, которые предполагается использовать в продакшене, «ну мы тут выкатим MVP и посмотрим, а там переделаем, если что» — это какой-то бред.
это не тот mvp который вы ищете, я про most vexing parse.
Неверно: <blablabla> является жёсткой ошибкой
Покажете SFINAE-проверку на валидность конструкции explicit(boolean-expr)
вы опять невнимательно прочитали, причем, шутки ради, тот кусок, который сами же и процитировали. Давайте еще раз: "Аксиома A: SFINAE позволяет проверить примерно любую языковую конструкцию на компилируемость". Я конечно сам виноват, опять опустил пару казалось бы очевидных вещей, но уход в глубокие частности, не имеющие абсолютно никакого отношения к контексту спора, вас никак не красит и доказать вашу точку зрения не помогает. Разница между "начала компилироваться конструкция S(1)" и "начала компилироваться конструкцияint T" не так существенна, как вы пытаетесь выдать. Как минимум потому, что ограничивать изменения языка по принципу покрытия SFINAE глупо. Особенно когда ваш пример проблемы построен на некорректном предусловии.
люди из комитета могут не отдавать себе отчета о том, что для человека "застрявшего" в C++03 переход на C++20/23 может выглядеть как переход на совсем другой язык программирования.
И, с учетом множества текущих факторов, для кого-то выбор между "изучать C++ заново" и "изучать Rust заново" будет отнюдь не в пользу C++.
вот мне прям сложно верится в человека, который 10 лет не желал обновить знания об инструменте, которым он денежку зарабатывает, потом захотел наверстать упущенное, столкнулся со сложностями решил, что изучать нововведения уже известного ему языка сложнее, чем изучать абсолютно новый язык.
Из прошлого опыта: заказчик из крупнейшего российского банка в 2008-2009 годах продолжал использовать Visual C++ 6.0 (которая года 1998 выпуска) и на вопросы "А почему бы вам не обновить VC++?" невозмутимо отвечал "А нам незачем".
таким объяснять надо. А то их так и будет всё устраивать, пока народ не начнет повально уходить на меньшую зарплату.
Это не то же самое, что поднять любую ошибку компиляции на уровень софтовых ошибок.
это даже не просто "абсолютно то же самое", это блин "оно самое". Вы буквально говорите о коде, поведение которого зависит от наличия ошибки компиляции определенного сниппета.
Почему нельзя было сразу использовать обычные скобочки для инициализации всего?
Надо было обойти MVP
На всякий случай переспрошу — вы серьёзно утверждаете, что <мина через ifdef> и SFINAE по <просто самый обычный SFINAE, никакого "по"> — это вещи одного порядка?
да, я серьезно это утверждаю. И единственная причина почему вам кажется это абсурдным - вы совершенно не понимаете/принимаете мою аргументацию. Ладно, давайте еще раз попробуем, вот вы вроде в ладах с математикой там, формальной логикой, верно? Аксиома A: SFINAE позволяет проверить примерно любую языковую конструкцию на компилируемость. Аксиома B: изменения в языке ведут к изменению компилируемости тех или иных языковых конструкций. Из B следует C: для любого изменения языка может существовать такая конструкция, поведение которой поменяется, тоже аксиома. Из A и C следует, что для любого изменения языка может существовать такая SFINAE проверка, поведение которой поменяется. Еще раз: для любого изменения. Соответственно, чтобы не ломать совсем никакой код, нужно всего навсего не менять язык. А еще компилятор и среду исполнения. Всё это вы можете организовать для себя сами.
Единственный способ обойти это, как я уже сказал, эпохи, механизм, который отсутствует не только в с++.
Когда ты все время на переднем крае, то вряд ли ты осознаешь, чем живут люди, которые вынуждены пользоваться C++11, а то и C++98.
во-первых, комитет регулярно проводит опросы, во-вторых, условный с++23 не поможет человеку, застрявшему на с++03, по той же причине, по которой ему не помогли с++11/14/17/20
Тогда, например, легко представить себе некий обобщённый библиотечный код, который отвечает за создание объектов и проверяет, принимает ли конструктор объекта QObject* (что может быть сделано через тот же is_constructible_v<T, QObject*> — пусть для простоты никаких других аргументов конструкторы принимать не могут)
ну блин, конструируемость от QObject* не является ни необходимым, ни достаточным условием QObject'а, нужен std::is_base_of_v<QObject, T>. Емнип даже не все QObject'ы умеют конструироваться только лишь от parent указателя
у вас после споров с царем лес за деревьями потерялся, ну что ж, будем помогать искать?
Чисто технически, кстати, нет, но неважно.
фактически, да, и это важно. SFINAE позволяет проверить корректность любой языковой конструкции, в т.ч. тех, которые еще не ввели в язык. Приведенная вами проблема является следствием мощности инструмента, а не ограниченности, никакой "скриптухой" тут и не пахнет, да и вообще оставьте царскую риторику, она вам не идет.
Всё, что меня волнует — могу ли я быть уверен, что после апгрейда компилятора и исправления ошибок компиляции мой код будет работать так, как ожидается, и могу ли я смело раскатывать его в прод или нет
Обсуждаемый код работал в точности так, как был написан - менял поведение при изменении стандарта языка. Абсолютно аналогично вы могли написать
Проблема не в этом - прикрутить версию реализации к версии стандарта наоборот было бы проще и правильнее, чем в некоторых конфигурациях предоставлять несовместимую стандарту реализацию.
Рассмотрим такой вариант: язык версионирован, и в двух версиях различается реализация какого-то класса std::foo. Казалось бы, всё просто - в одном режиме будет using cpp_23::foo; а в другом - using cpp_26::foo; Нюанс в том, что разработчикам компиляторов придется не только поддерживать обе версии класса, но еще и писать конвертации/interop между ними. Это приведет к экспоненциальному росту сложности поддержки от числа изменений, чего разработчики компиляторов естественно не хотят
Есть три класса изменений: те, которые не приводят к смене поведения; те, которые приводят к ошибке компиляции; и те, которые приводят к изменению поведения в рантайме
я вам еще раз объясняю - первое невозможно без эпох, а второе, из-за sfinae, является подмножеством третьего. И ваш конкретный случай - когда второе перетекло в третье, как раз посредством sfinae. И соответственно вот это утверждение:
То, что в данном конкретном случае речь идёт о sfinae, который как-то связан с ошибками компиляции (в основном наличием слова «ошибка» и там, и там), не играет вообще никакой роли.
в корне неверно для вашего же конкретного случая. Блин, да даже по определению, в с++17 у вас substitution failure of T with S is not an error, в с++20 substitution success.
Вы в ответ вспоминаете про noexcept и constexpr, которые приводят к ошибке компиляции, да ещё и пишете что-то про то, что это та же логика.
Во-первых, sfinae в принципе работает через проверку скомпилируется та или иная конструкция или нет, перегрузки с ошибкой компиляции не выбираются. Так ваш снипеет и переводит ошибку компиляции в рантайм - до c++20 конструкция S(1) просто не соберется. Во-вторых, с точки зрения моего изначального аргумента даже не важно, что там за ошибки, компиляции или рантайма. Попробую его перефразировать: если исходить из установки, что на любое изменения языка обязательно найдется существующий код, зависящий от этого изменения, и его нельзя ломать, то развивать язык становится невозможно.
Просто представьте себя на месте человека из комитета, и поймете, что ваша претензия сейчас сродни плачу вредного ребенка.
В данном случае это тождественно "не добавлять новую функциональность вообще", и я комментом выше объяснил почему. По такой же логике можно было бы обижаться на комитет за сломавшийся с++03 код, называющий переменные noexcept и constexpr.
Limiter хранит все квоты и счётчики в памяти и регулярно синхронизируется с корневым сервером (YARL root), получая от него оперативную информацию о свежих значениях.
а как боретесь с выпадением/обновлением root'а? Что будет, если он окажется перегружен?
isCpp20 вернёт true при сборке C++20-компилятором, и false при сборке C++17-компилятором.
Ваш пример можно упростить доstd::is_constructible_v<S, int>. Весьма логично, что при добавлении в язык нового функционала, SFINAE, проверяющий против этого функционала, начнет работать иначе. А еще логично что избежать такой проблемы без эпох, которых в плюсах нет, невозможно. Ну или любого другого механизма прибивания версии языка к коду гвоздями. Да и не только в плюсах.
А из рекомендаций только один — сходить проверить голову. И я говорю это по доброте душевной, а не потому, что хочу выставить вас в плохом свете или не дай бог издеваюсь над больным человеком.
я конечно понимаю, что скомпилировать поток сознания ncwca еще сложнее чем плюсы, но как бы парадоксально это ни звучало, тут я с ним соглашусь. Нюанс в том, что вот эта проблема:
Вы считаете, что ваш С++ правильный, а 100 других контрибьюторов считают что их
потихоньку отмирает т.к. в современных плюсах народ постепенно приближается к некоторому единому стилю, с редкими domain-specific оговорками. Тот же гугл, например, отказался в своих гайдлайнах от правил наподобие "не используйте mutable references". Да, я согласен, это всё еще не обязательный линтер который на каждый кривой отступ будет посылать к чертовой бабушке, но тем не менее того разброда и шатания, что был лет 20 назад, в новых кодобазах не встретишь.
Ага, эту манцу мы слыхали, только есть небольшая проблема — этому не бывать. Никто не будет выкидывать совместимость. Это не считая миллиона других проблем, но не будем об этом, мы же не шарим.
подскажите, как у вас смешались понятия "совместимость" и "легаси"? Да, существует старый код на старом плюсовом диалекте, новый код пишут на новом диалекте, в чем проблема-то? Рано или поздно код на расте тоже отлежится, завоняет и станет легаси, это если раст не вымрет. Вы будете ждать этого чтобы поменять свою точку зрения, или можете сразу, дальновидно, поменять её с учетом такой перспективы?
А теперь давайте посмотрим, что же говорит сам Линус.
да, давайте подкреплять свой беспочвенный хейт цитированием хейтера, известного своей неадекватностью, который свой хейт ничем никогда не обосновывал, ведь именно так действуют думающие люди... нет, конечно же. Хотите конструктивной дискуссии - вносите конструктив, анализ, и объективные аргументы. Пока что вы лишь перевбрасываете чужие вбросы
вы вообще даже конвертацию строки в число не написали
я писал свой сниппет с целью показать, что никакие "глубокие знания ренджей" не нужны, и, надеюсь, с этой задачей справился. Я нарочно опустил парсинг, т.к. он бы лишь увеличил сниппет, не преследуя эту цель. Вы же написали свой сниппет преследуя цель продемонстрировать какой раст красивый/хороший/лаконичный на фоне с++, спрятав в нём панику. И моя претензия даже не в том, что production-ready сниппет на расте должен выглядеть иначе, а в том, что писать код запихивая обработку ошибок под ковер в принципе не стоит ни в одном из языков.
Вы правда думаете что в 99% мне не наплевать на эти аллокации?
Конечно же нет. Однако такие API противоречат самой сути с++ как zerocost-oriented языка. В конце концов, вы всегда можете написать неэффективный код на эффективном языке, но не наоборот.
В стандартной библиотеке дофига классов которые можно написать более оптимально
а можете привести пару примеров? Так, чтобы альтернативная реализация могла бы быть безусловно лучше, без опускания части требований/гарантий.
Так и в C++23 это есть, если лишние аллокации ок:
боюсь std::string{s} (где s - subrange<const char*, const char*>) не скомпилится.
давайте сравним: Qt версия делает на N + log(N) аллокаций больше, то есть выразительность в ущерб производительности. Соответственно, такой версии split не место в стандарте.
Но что еще важнее, Qt это всё еще плюсы. На плюсах вы всегда можете написать библиотеку с любым желаемым соотношением выразительности/производительности, а новички всегда могут начать изучать с++ с того же Qt
так пользовательский код зависит от стандартного... вот например в с++20 добавили
std::string::starts_with, а значит поменялся пользовательский код, диспатчащий по наличиюT::starts_with. Значит ли это, что метод не стоило добавлять?а в кошерном SFINAE
return false, как же так?то, что вы где-то у себя выяснили, всё еще имеет весьма опосредственное и натянутое отношение к действительности.
а изменения нужны, и не только посредством новых синтаксических конструкций. Вы очень старательно упускаете тот нюанс что в с++17
S(1)не компилировался.хорошо, одну вещь я таки наконец-то доказал, аллелуйа. Теперь осталось доказать что доля кода, поведение которого зависит от компилируемости будущих синтаксических конструкций, ничтожно мала, и вы будете еще на шаг ближе к пониманию истины.
я утверждаю, что с++ обеспечивает тот уровень обратной совместимости, который можно сохранить попутно обновляя язык.
тогда поднимайте белый флаг
SFINAE проверяет ровно то, что передали в контекст подстановки. Если в этом контексте есть ошибка - подстановка провалится.
это не тот mvp который вы ищете, я про most vexing parse.
вы опять невнимательно прочитали, причем, шутки ради, тот кусок, который сами же и процитировали. Давайте еще раз: "Аксиома A: SFINAE позволяет проверить примерно любую языковую конструкцию на компилируемость". Я конечно сам виноват, опять опустил пару казалось бы очевидных вещей, но уход в глубокие частности, не имеющие абсолютно никакого отношения к контексту спора, вас никак не красит и доказать вашу точку зрения не помогает. Разница между "начала компилироваться конструкция
S(1)" и "начала компилироваться конструкцияint T" не так существенна, как вы пытаетесь выдать. Как минимум потому, что ограничивать изменения языка по принципу покрытия SFINAE глупо. Особенно когда ваш пример проблемы построен на некорректном предусловии.вот мне прям сложно верится в человека, который 10 лет не желал обновить знания об инструменте, которым он денежку зарабатывает, потом захотел наверстать упущенное, столкнулся со сложностями решил, что изучать нововведения уже известного ему языка сложнее, чем изучать абсолютно новый язык.
таким объяснять надо. А то их так и будет всё устраивать, пока народ не начнет повально уходить на меньшую зарплату.
это даже не просто "абсолютно то же самое", это блин "оно самое". Вы буквально говорите о коде, поведение которого зависит от наличия ошибки компиляции определенного сниппета.
Надо было обойти MVP
да, я серьезно это утверждаю. И единственная причина почему вам кажется это абсурдным - вы совершенно не понимаете/принимаете мою аргументацию. Ладно, давайте еще раз попробуем, вот вы вроде в ладах с математикой там, формальной логикой, верно? Аксиома A: SFINAE позволяет проверить примерно любую языковую конструкцию на компилируемость. Аксиома B: изменения в языке ведут к изменению компилируемости тех или иных языковых конструкций. Из B следует C: для любого изменения языка может существовать такая конструкция, поведение которой поменяется, тоже аксиома. Из A и C следует, что для любого изменения языка может существовать такая SFINAE проверка, поведение которой поменяется. Еще раз: для любого изменения. Соответственно, чтобы не ломать совсем никакой код, нужно всего навсего не менять язык. А еще компилятор и среду исполнения. Всё это вы можете организовать для себя сами.
Единственный способ обойти это, как я уже сказал, эпохи, механизм, который отсутствует не только в с++.
во-первых, комитет регулярно проводит опросы, во-вторых, условный с++23 не поможет человеку, застрявшему на с++03, по той же причине, по которой ему не помогли с++11/14/17/20
ну блин, конструируемость от
QObject*не является ни необходимым, ни достаточным условием QObject'а, нуженstd::is_base_of_v<QObject, T>. Емнип даже не все QObject'ы умеют конструироваться только лишь от parent указателяу вас после споров с царем лес за деревьями потерялся, ну что ж, будем помогать искать?
фактически, да, и это важно. SFINAE позволяет проверить корректность любой языковой конструкции, в т.ч. тех, которые еще не ввели в язык. Приведенная вами проблема является следствием мощности инструмента, а не ограниченности, никакой "скриптухой" тут и не пахнет, да и вообще оставьте царскую риторику, она вам не идет.
Обсуждаемый код работал в точности так, как был написан - менял поведение при изменении стандарта языка. Абсолютно аналогично вы могли написать
и потом жаловаться что ничего не работает
Проблема не в этом - прикрутить версию реализации к версии стандарта наоборот было бы проще и правильнее, чем в некоторых конфигурациях предоставлять несовместимую стандарту реализацию.
Рассмотрим такой вариант: язык версионирован, и в двух версиях различается реализация какого-то класса
std::foo. Казалось бы, всё просто - в одном режиме будетusing cpp_23::foo;а в другом -using cpp_26::foo;Нюанс в том, что разработчикам компиляторов придется не только поддерживать обе версии класса, но еще и писать конвертации/interop между ними. Это приведет к экспоненциальному росту сложности поддержки от числа изменений, чего разработчики компиляторов естественно не хотятя вам еще раз объясняю - первое невозможно без эпох, а второе, из-за sfinae, является подмножеством третьего. И ваш конкретный случай - когда второе перетекло в третье, как раз посредством sfinae. И соответственно вот это утверждение:
в корне неверно для вашего же конкретного случая. Блин, да даже по определению, в с++17 у вас substitution failure of T with S is not an error, в с++20 substitution success.
Во-первых, sfinae в принципе работает через проверку скомпилируется та или иная конструкция или нет, перегрузки с ошибкой компиляции не выбираются. Так ваш снипеет и переводит ошибку компиляции в рантайм - до c++20 конструкция
S(1)просто не соберется. Во-вторых, с точки зрения моего изначального аргумента даже не важно, что там за ошибки, компиляции или рантайма. Попробую его перефразировать: если исходить из установки, что на любое изменения языка обязательно найдется существующий код, зависящий от этого изменения, и его нельзя ломать, то развивать язык становится невозможно.Просто представьте себя на месте человека из комитета, и поймете, что ваша претензия сейчас сродни плачу вредного ребенка.
В данном случае это тождественно "не добавлять новую функциональность вообще", и я комментом выше объяснил почему. По такой же логике можно было бы обижаться на комитет за сломавшийся с++03 код, называющий переменные noexcept и constexpr.
а как боретесь с выпадением/обновлением root'а? Что будет, если он окажется перегружен?
Ваш пример можно упростить до
std::is_constructible_v<S, int>. Весьма логично, что при добавлении в язык нового функционала, SFINAE, проверяющий против этого функционала, начнет работать иначе. А еще логично что избежать такой проблемы без эпох, которых в плюсах нет, невозможно. Ну или любого другого механизма прибивания версии языка к коду гвоздями. Да и не только в плюсах.я конечно понимаю, что скомпилировать поток сознания ncwca еще сложнее чем плюсы, но как бы парадоксально это ни звучало, тут я с ним соглашусь. Нюанс в том, что вот эта проблема:
потихоньку отмирает т.к. в современных плюсах народ постепенно приближается к некоторому единому стилю, с редкими domain-specific оговорками. Тот же гугл, например, отказался в своих гайдлайнах от правил наподобие "не используйте mutable references". Да, я согласен, это всё еще не обязательный линтер который на каждый кривой отступ будет посылать к чертовой бабушке, но тем не менее того разброда и шатания, что был лет 20 назад, в новых кодобазах не встретишь.
подскажите, как у вас смешались понятия "совместимость" и "легаси"? Да, существует старый код на старом плюсовом диалекте, новый код пишут на новом диалекте, в чем проблема-то? Рано или поздно код на расте тоже отлежится, завоняет и станет легаси, это если раст не вымрет. Вы будете ждать этого чтобы поменять свою точку зрения, или можете сразу, дальновидно, поменять её с учетом такой перспективы?
да, давайте подкреплять свой беспочвенный хейт цитированием хейтера, известного своей неадекватностью, который свой хейт ничем никогда не обосновывал, ведь именно так действуют думающие люди... нет, конечно же. Хотите конструктивной дискуссии - вносите конструктив, анализ, и объективные аргументы. Пока что вы лишь перевбрасываете чужие вбросы
я писал свой сниппет с целью показать, что никакие "глубокие знания ренджей" не нужны, и, надеюсь, с этой задачей справился. Я нарочно опустил парсинг, т.к. он бы лишь увеличил сниппет, не преследуя эту цель. Вы же написали свой сниппет преследуя цель продемонстрировать какой раст красивый/хороший/лаконичный на фоне с++, спрятав в нём панику. И моя претензия даже не в том, что production-ready сниппет на расте должен выглядеть иначе, а в том, что писать код запихивая обработку ошибок под ковер в принципе не стоит ни в одном из языков.
stacktrace не добавляет накладных расходов при создании исключения, только при вызове stacktrace::current.
"Так, чтобы альтернативная реализация могла бы быть безусловно лучше, без опускания части требований/гарантий."
не шибко то и интересно - ваш код будет падать на любом некорректном вводе.
Конечно же нет. Однако такие API противоречат самой сути с++ как zerocost-oriented языка. В конце концов, вы всегда можете написать неэффективный код на эффективном языке, но не наоборот.
а можете привести пару примеров? Так, чтобы альтернативная реализация могла бы быть безусловно лучше, без опускания части требований/гарантий.
боюсь std::string{s} (где s - subrange<const char*, const char*>) не скомпилится.
давайте сравним: Qt версия делает на N + log(N) аллокаций больше, то есть выразительность в ущерб производительности. Соответственно, такой версии split не место в стандарте.
Но что еще важнее, Qt это всё еще плюсы. На плюсах вы всегда можете написать библиотеку с любым желаемым соотношением выразительности/производительности, а новички всегда могут начать изучать с++ с того же Qt