170 похожих чатов

Народ, возможно ли в С++ написать constexpr-функцию которая парсит число

из строки и выдает разный тип в зависимости от значения (или int или double) ?
static_assert(parseNumber("123") == 123);
static_assert(parseNumber("123.123") == 123.123);
Или так в С++ сделать невозможно и мы вынуждены передавать строку через шаблонный параметр?
static_assert(parseNumber<"123">() == 123);
static_assert(parseNumber<"123.123">() == 123.123);

40 ответов

77 просмотров

нет нельзя, лучшее что можно это вариант

предположим, что возможно. какая у неё сигнатура?

Первое опять про constexpr-параметры (которых нет).

feedable
ну дефолтное auto(auto)

это не сигнатура. в сигнатуре конкретные типы

feedable
да нет они тут не нужны

Хочется в constexpr-контекст внутри (или в trailing-type) затащить значение параметра. Как не нужны?)

Sergey Anisimov
Хочется в constexpr-контекст внутри (или в trailin...

тут можно было бы сделать так чтоб принимаемый параметр был рантаймовым

feedable
через рассахаривание-варианта

А, это опять про то предложение...

feedable
через рассахаривание-варианта

Давай обсуждать C++, а не выдуманный язык

Богдан- Автор вопроса
Sergey Anisimov
Первое опять про constexpr-параметры (которых нет)...

кажется я понял, ну что ж, будем ждать constexpr-параметры в С++26 стандарте

Богдан
кажется я понял, ну что ж, будем ждать constexpr-п...

Не будем, вроде же комитет сказал, что компиляторы не осилят, так как слишком больно текущим реализациям будет

Богдан- Автор вопроса

А пока я пытаюсь реализовать вариант с передачей строки через шаблонный параметр и не могу понять как в if-constexpr/if-consteval задетектить ошибку компиляции (или компайл-тайм интерпретации) которая выбрасывается consteval-функцией через throw чтобы при интанциировании была отброшена ненужная ветка и auto не ругался на то что мы возвращаем разные типы Вариант 1 (через if-consteval) template <string_literal str> constexpr auto parseNumber() { if consteval { return stoi(str.value); } else { return stod(str.value); } } int main(){ static_assert(parseNumber<"123">() == 123); static_assert(parseNumber<"123.123">() == 123); } не работает и ругается на несовпадение типов возврата: error: inconsistent deduction for auto return type: 'int' and then 'double' Вариант 2 (через if-constexpr + requires{..}) template <string_literal str> consteval auto parseNumber() { if constexpr(requires { stoi(str.value); }) { return stoi(str.value); } else { return stod(str.value); } } int main(){ static_assert(parseNumber<"123">() == 123); static_assert(parseNumber<"123.123">() == 123); } не работает и ругается на error: expression '<throw-expression>' is not a constant expression Вот полная демка - https://godbolt.org/z/jGqcfhvKs Кто-нибудь может объяснить это поведение и как это можно решить?

Возможно

Богдан
кажется я понял, ну что ж, будем ждать constexpr-п...

вообще если тебе пофиг на рантайм то можешь юзать хана::тайп_ц

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

В чем тут сложность реализации? Разве constexpr-параметры это не синтаксический сахар? Компилятору достаточно посмотреть что параметр объявлен как constexpr и будет трактовать его как шаблонный параметр. То есть вот такой код auto someFunc(constexpr string_literal str, auto someParam){ ... } Будет эквивалентен такому коду template<string_literal str> auto someFunc(auto someParam){ ... }

Богдан
В чем тут сложность реализации? Разве constexpr-па...

предыдущие пропозалы делали так что констекспр это и кт и рт может быть

Делается тривиально кстати

d7d1cd
Нуу. Покажите как

ну второе реально делается, тривиальная реализация: в constexpr ищем . и это делаем в отдельной consteval функции

Богдан
А пока я пытаюсь реализовать вариант с передачей с...

std::from_chars не бросает исключение. Жаль тоже не constexpr

Alexander Karaev
constexpr частично, только для целых

Оу, а я думаю где надпись-то. А она в зелёной скобке. Обычно constexpr версия выписана отдельно

Alexander Karaev
constexpr частично, только для целых

И это очень хорошо. Потому что все преобразования для floating в любых направлениях дикий матан.

Jokhar Ali
https://godbolt.org/z/Whs6KG1hj

Стринг литерал, кстати, необязательно создавать отдельно

Андрей Будиловский
Стринг литерал, кстати, необязательно создавать от...

Так оно для наглядности ты можешь сразу ее подсунуть

Богдан- Автор вопроса

Спасибо за пример. Но по-прежнему остается вопрос почему if consteval {} не умеет отбрасывать ветку (которая не может выполниться в компайл-тайме) при интанциировании функции. То есть я пытаюсь запарсить число из строки в компайл-тайме int stoi(const char*); double stod(const char*); template <string_literal str> constexpr auto parseNumber() { if consteval { return stoi(str.value); } else { return stod(str.value); } } и процессе компайлт-тайм интерпретации вызывается функция stoi которая выбрасывает исключение через throw. Но throw это невалидная конструкция для constexpr-функции и по идее компилятор должен обросить первую ветку и перейти к else-ветке при инстанциирования но этого не происходит и компилятор ругается на неконсистетность типа возрата Но еще больше меня беспокоит почему конструкция if constexpr(requires { stoi(str.value); }){ return stoi(str.value); } else { return stoi(str.value); } не может поймать ошибку, ведь это сильно похоже на обращение к несуществующим полям на объекте struct X { int field; } struct Y { int someField; } auto func(auto obj){ if constexpr(requires{ obj.someField }) { obj.someField; } else { obj.field; } } int main(){ func(X{}); func(Y{}); } Или ответ заключается в том что конструкция if constexpr(requires{ ... }){ ... } может ловить лишь sfinae-out ошибки компиляции а throw при компайл-тайм выполнении constexpr функции это уже "hard error" ??

Второе

Богдан- Автор вопроса
Jokhar Ali
Второе

Интересно, а есть ли где-то обсуждения почему так решили? Или может не захотели усложнять? Интересно есть ли уже пропозал к С++26 про то чтобы перевести throw-ошибки (для constexpr-функций) в разряд sfinae-out ошибок?

Богдан
Спасибо за пример. Но по-прежнему остается вопрос ...

if consteval {} выбирает ветку if, если вычисление функции происходит в ct, иначе ветку else От внутренностей веток if consteval {} не зависит. Она уже выполняется либо так, либо эдак

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Подскажите пожалуйста, как в CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); получить наз...
A Z
7
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Раз начали говорить про embassy, то присоединюсь со своими парой вопросов. 1) Есть ли сопоставимые аналоги для асинхронного кода в emdebbed? 2) Можно ли внутри задач embassy ...
NI_isx
6
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
1
Он в одиночку это дело запилил или была какая-то команда?
Aquinary
12
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Карта сайта