S>Теперь такая возможность появляется (т.е. функцию f из примера выше можно объявить constexpr) но не хочется "проглатывать" исключения, если они происходят в compile-time.
Да, только в этом сценарии отсутсвует долгожданное "try-catch в constexpr функции"
--
Справедливость выше закона. А человечность выше справедливости.
S>>Теперь такая возможность появляется (т.е. функцию f из примера выше можно объявить constexpr) но не хочется "проглатывать" исключения, если они происходят в compile-time.
R>Да, только в этом сценарии отсутсвует долгожданное "try-catch в constexpr функции"
Почему отсутствует? Была просто f() показанная выше, стала:
template<typename T>
constexpr int f() {
try {
return T::some_func();
}
catch(...) {
// Ну не шмогли, ну и ладно.return 0;
}
}
Но в таком варианте выражение T::some_func() заведомо не может быть источником исключения, иначе это просто не скомпилируется (или я чего-то не знаю). Отсюда снова вопрос о ценности try-catch в constexpr функции. Вопрос же именно о ценности, а не о том, какова могла быть предыстория образования данного кода.
--
Справедливость выше закона. А человечность выше справедливости.
R>Но в таком варианте выражение T::some_func() заведомо не может быть источником исключения, иначе это просто не скомпилируется (или я чего-то не знаю). Отсюда снова вопрос о ценности try-catch в constexpr функции. Вопрос же именно о ценности, а не о том, какова могла быть предыстория образования данного кода.
Так там не зря же вызывается some_func из T. В зависимости от T это могут быть как some_func с исключениями внутри, так и без исключений.
Грубо говоря:
struct constexpr_ready_traits {
static constexpr int some_func() { return 0; }
};
struct runtime_only_traits {
static int some_func() {
if(is_appropriate_moon_phase()) throw std::runtime_error{ "Not now, bro!" };
return 42;
}
};
constexpr int f1 = f<constexpr_ready_traits>();
int f2 = f<runtime_only_traits>();
Вроде все сходится.
Тут другой вопрос: зачем внутри f пытаться делать проверку на наличие исключений в compile-time, но этот вопрос тов.Videoman уже объяснил.
#include <type_traits>
#include <optional>
int func_runtime()
{
// use intrinsics, threads or other staff throw int();
}
constexpr int func_constexpr() noexcept
{
// no optimizationreturn 0;
}
constexpr int func() noexcept
{
if (std::is_constant_evaluated())
return func_constexpr();
else {
try {
return func_runtime();
} catch (...) {
return 0;
}
}
}
int main()
{
constexpr int value1 = func();
int value2 = func();
return value1 + value2;
}
Иногда в для того, что бы код работал в runtime`е быстро, там приходится использовать низкоуровневые возможности, а constexpr не позволяет такое миксовать. Теперь можно писать код, которые будет работать и в том и в том режиме.
Здравствуйте, Videoman, Вы писали:
V>Теперь можно писать код, которые будет работать и в том и в том режиме.
Возможно, я что-то упускаю, но вся эта чехарда с constexpr/consteval больше похожа на поддержку очередного набора трюков, нежели на средства выражения замысла программиста.
Поскольку компилятор всегда видит все зависимости между данными, ему не требуется явного указания constexpr, чтобы вычислить при компиляции выражение, если оно технически вычислимо. Единственное, что здесь может быть полезно — это consteval/constinit, чтобы получить ошибку, если выражение не удается вычислить во время компиляции.
Соответственно, функция вроде Вашей сильно смахивает на дверь, в петлю которой вставлена дужка незапертого замка. То ли пытались запереть, но забыли или не сумели, то ли просто не нашлось ничего более подходящего, чтоб сама не распахивалась.
Здравствуйте, Евгений Музыченко, Вы писали:
V>>Теперь можно писать код, которые будет работать и в том и в том режиме.
ЕМ>Возможно, я что-то упускаю, но вся эта чехарда с constexpr/consteval больше похожа на поддержку очередного набора трюков, нежели на средства выражения замысла программиста.
И?
Даже если вы и правы, то что следует? Следует перестать использовать constexpr/consteval? Следует написать пропозал об отмене constexpr/consteval и попробовать провести его через комитет, чтобы в C++29 и C++32 ключевые слова constexpr/consteval для функций/методов сделали опциональными?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Соответственно, функция вроде Вашей сильно смахивает на дверь, в петлю которой вставлена дужка незапертого замка. То ли пытались запереть, но забыли или не сумели, то ли просто не нашлось ничего более подходящего, чтоб сама не распахивалась.
Проблема не в том, что бы вычислять на этапе компиляции, а в том, что не хочется писать код отдельно для compile-time и отдельно для run-time. Представь, что 95% кода работает именно так, как ты говоришь, но где-то в потрохах вызывается функция, которая не может быть выполнена в compile-time. Теперь такое можно поддерживать, просто имея две реализации одной функции, имея остальной код в единственном экземпляре.