из строки и выдает разный тип в зависимости от значения (или 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);
нет нельзя, лучшее что можно это вариант
предположим, что возможно. какая у неё сигнатура?
ну дефолтное auto(auto)
Первое опять про constexpr-параметры (которых нет).
да нет они тут не нужны
это не сигнатура. в сигнатуре конкретные типы
Хочется в constexpr-контекст внутри (или в trailing-type) затащить значение параметра. Как не нужны?)
тут можно было бы сделать так чтоб принимаемый параметр был рантаймовым
А как разный тип будет тогда, упускаю?
что за вариант?
std::variant
через рассахаривание-варианта
А, это опять про то предложение...
Давай обсуждать C++, а не выдуманный язык
кажется я понял, ну что ж, будем ждать constexpr-параметры в С++26 стандарте
Не будем, вроде же комитет сказал, что компиляторы не осилят, так как слишком больно текущим реализациям будет
А что, были предложения, не ломающие язык?
А пока я пытаюсь реализовать вариант с передачей строки через шаблонный параметр и не могу понять как в 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 и будет трактовать его как шаблонный параметр. То есть вот такой код auto someFunc(constexpr string_literal str, auto someParam){ ... } Будет эквивалентен такому коду template<string_literal str> auto someFunc(auto someParam){ ... }
там гвоздями всё прибито, что это не так
предыдущие пропозалы делали так что констекспр это и кт и рт может быть
Ломаются всякие is_invocable
Делается тривиально кстати
Нуу. Покажите как
ну второе реально делается, тривиальная реализация: в constexpr ищем . и это делаем в отдельной consteval функции
std::from_chars не бросает исключение. Жаль тоже не constexpr
constexpr частично, только для целых
Оу, а я думаю где надпись-то. А она в зелёной скобке. Обычно constexpr версия выписана отдельно
И это очень хорошо. Потому что все преобразования для floating в любых направлениях дикий матан.
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" ??
Второе
Интересно, а есть ли где-то обсуждения почему так решили? Или может не захотели усложнять? Интересно есть ли уже пропозал к С++26 про то чтобы перевести throw-ошибки (для constexpr-функций) в разряд sfinae-out ошибок?
Потому что оно так всегда работало
if consteval {} выбирает ветку if, если вычисление функции происходит в ct, иначе ветку else От внутренностей веток if consteval {} не зависит. Она уже выполняется либо так, либо эдак
Обсуждают сегодня