Re: static_assert в catch секции
От: rg45 СССР  
Дата: 21.12.24 14:44
Оценка: 78 (2)
Здравствуйте, Videoman, Вы писали:

V>Как известно в С++20 подвезли возможность использовать try catch блоки внутри constexpr выражений. Стало удобно, но появилась следующая проблема:


V>Есть функция func1(), которая без проблем работает в constexpr режиме и есть внешняя функция func2(), которая никогда не должна выкидывать исключения, которая вызывает внутри себя первую, типа такого:
V>template<typename...>
V>inline constexpr bool always_false = false;

V>template<typename type_t>
V>constexpr int func2() noexcept
V>{
V>  try {
V>    return func1();
V>  } catch (...) {
V>    static_assert(always_false<type_t>, "error!");
V>    return 0;
V>  }
V>}
V>

V>Так вот, стандартный подход с always_false тут не прокатывает и static_assert срабатывает всегда, а мне нужно что бы он срабатывал только если возникло исключение. Как такое можно организовать?

Ну да, для того, чтобы это сработало, компилятор должен исключить этот static_assert из компиляции. А у него для этого нет поводов. Тут нужно как-то адаптировать дизайн. Например, обернуть в constexpr if:

http://coliru.stacked-crooked.com/a/d21b3db809532a31

#include <exception>
#include <utility>

template<typename...>
inline constexpr bool always_false = false;

constexpr int func1()
{
    return 1;
}

template<typename type_t>
constexpr int func2() noexcept
{
  constexpr auto call_func1 = []() -> std::pair<int, bool> {
    try {
      return {func1(), true};
    } catch (...) {
      return {};
    }
  };    
  constexpr auto res = call_func1();

  if constexpr (res.second) return res.first;
  else static_assert(always_false<type_t>, "error!");
}

int main()
{
  return func2<int>();
}
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 23.12.24 15:35
Оценка: 19 (2)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Нынче считается, что это способствует ясности изложения кода?


А причем тут ясность? Тут необходимость просто:
#include <type_traits>
#include <optional>

int func_runtime()
{
    // use intrinsics, threads or other staff 

    throw int();
}

constexpr int func_constexpr() noexcept
{
    // no optimization

    return 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 не позволяет такое миксовать. Теперь можно писать код, которые будет работать и в том и в том режиме.
Отредактировано 23.12.2024 15:36 Videoman . Предыдущая версия .
Re: static_assert в catch секции
От: Chorkov Россия  
Дата: 23.12.24 09:05
Оценка: 15 (2)
Здравствуйте, Videoman, Вы писали:

V>Как известно в С++20 подвезли возможность использовать try catch блоки внутри constexpr выражений. Стало удобно, но появилась следующая проблема:


V>Есть функция func1(), которая без проблем работает в constexpr режиме и есть внешняя функция func2(), которая никогда не должна выкидывать исключения, которая вызывает внутри себя первую, типа такого:
V>template<typename...>
V>inline constexpr bool always_false = false;

V>template<typename type_t>
V>constexpr int func2() noexcept
V>{
V>  try {
V>    return func1();
V>  } catch (...) {
V>    static_assert(always_false<type_t>, "error!");
V>    return 0;
V>  }
V>}
V>

V>Так вот, стандартный подход с always_false тут не прокатывает и static_assert срабатывает всегда, а мне нужно что бы он срабатывал только если возникло исключение. Как такое можно организовать?

Если func1 помечена как noexcept, то достаточно проверить это:
https://en.cppreference.com/w/cpp/language/noexcept
template<typename type_t>
constexpr int func2() noexcept
{
  static_assert( noexcept( func1() ) );
  return func1();
}



Или, если не помечено, то можно сделать проверку, использця идею rg45:
template<auto Func>
constexpr bool is_constexpr_noexcept() noexcept
{
    try {
      Func();
      return true;
    } catch (...) {
      return false;
    }
}

template<typename type_t>
constexpr int func2() noexcept
{
  static_assert( is_constexpr_noexcept< func1 >() ) ;
  return func1();
}


Правда, тут есть подложенные грабли: в C++23 func1 может менять поведение, в процессе compile-time вычислений:
#include <exception>
#include <exception>
#include <utility>

constexpr int func1()
{
    if consteval
    {
        return 1;
    }
    else
    {
        throw 42;
    }
}

template<auto Func>
constexpr bool is_constexpr_noexcept() noexcept
{
    try {
      Func();
      return  true;
    } catch (...) {
      return false;
    }
}
template<typename type_t>
constexpr int func2() noexcept
{
  static_assert( is_constexpr_noexcept< func1 >() ) ;
  constexpr auto result = func1();
  return result;
}

int main()
{
  return func2<int>(); // throw 42, если не сделать constexpr auto result в func2;
}
Re[3]: static_assert в catch секции
От: rg45 СССР  
Дата: 21.12.24 15:05
Оценка: :))
Здравствуйте, Videoman, Вы писали:

V>Делал именно таким методом, но было подумал, что занимаюсь извращением и как-то сложно получается. Вот решил спросить у более опытных коллег. Интересно имменно в рамках 20-го стандарта.


Ну, ждём более опытных
--
Справедливость выше закона. А человечность выше справедливости.
Re: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 22.12.24 05:45
Оценка: +2
Здравствуйте, Videoman, Вы писали:

V>Как известно в С++20 подвезли возможность использовать try catch блоки внутри constexpr выражений.


А как в рамках C++20 (и даже C++23) бросить исключение в compile-time?
Re[8]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 23.12.24 12:23
Оценка: 12 (1)
Здравствуйте, rg45, Вы писали:

S>>Почему отсутствует? Была просто f() показанная выше, стала:

S>>
S>>template<typename T>
S>>constexpr int f() {
S>>  try {
S>>    return T::some_func();
S>>  }
S>>  catch(...) {
S>>    // Ну не шмогли, ну и ладно.
S>>    return 0;
S>>  }
S>>}
S>>


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 уже объяснил.
Re[3]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 22.12.24 13:18
Оценка: +1
Здравствуйте, Videoman, Вы писали:

S>>А как в рамках C++20 (и даже C++23) бросить исключение в compile-time?


V>Также как с выделением памяти. Если весь процесс остается внутри и все сайд эффекты compile-time, но всё работает. Сама внешняя функция noexcept, наружу ничего не летит.


Простите, понятнее не стало. В C++20 разве можно написать constexpr-функцию, которая бросает исключение в compile-time?

А если нет, то зачем защищаться от исключений, которые в compiler-time могут возникнуть, если возникнуть им неоткуда?
Re: static_assert в catch секции
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 22.12.24 14:10
Оценка: +1
Здравствуйте, Videoman, Вы писали:

V>Как известно в С++20 подвезли возможность использовать try catch блоки внутри constexpr выражений. Стало удобно


Если не секрет, что именно стало удобно с появлением этой возможности?
Re[5]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 23.12.24 03:49
Оценка: +1
Здравствуйте, Videoman, Вы писали:

V>Здравствуйте, so5team, Вы писали:


V>Ну запутали, так запутали!!!


Простите, не понял, что означает ваш ответ с фейспалмом.

И получается какая-то странная ситуация: вы задаете вопрос, я пытаюсь набросать решение и сталкиваюсь с тем, что не могу его протестировать, т.к. в C++20 (C++23) нет возможности бросить исключение из constexpr-функции в компайл-тайм. Понимаю, что чего-то не понимаю в постановке задачи, задаю уточняющие вопросы, а в ответ фейспалм.

Абыдна, да.
static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 21.12.24 12:25
Оценка:
Как известно в С++20 подвезли возможность использовать try catch блоки внутри constexpr выражений. Стало удобно, но появилась следующая проблема:

Есть функция func1(), которая без проблем работает в constexpr режиме и есть внешняя функция func2(), которая никогда не должна выкидывать исключения, которая вызывает внутри себя первую, типа такого:
template<typename...>
inline constexpr bool always_false = false;

template<typename type_t>
constexpr int func2() noexcept
{
  try {
    return func1();
  } catch (...) {
    static_assert(always_false<type_t>, "error!");
    return 0;
  }
}

Так вот, стандартный подход с always_false тут не прокатывает и static_assert срабатывает всегда, а мне нужно что бы он срабатывал только если возникло исключение. Как такое можно организовать?
Отредактировано 21.12.2024 13:19 Videoman . Предыдущая версия .
Re: static_assert в catch секции
От: rg45 СССР  
Дата: 21.12.24 14:49
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Как известно в С++20 подвезли возможность использовать try catch блоки внутри constexpr выражений. Стало удобно, но появилась следующая проблема:


V>Есть функция func1(), которая без проблем работает в constexpr режиме и есть внешняя функция func2(), которая никогда не должна выкидывать исключения, которая вызывает внутри себя первую, типа такого:
V>template<typename...>
V>inline constexpr bool always_false = false;

V>template<typename type_t>
V>constexpr int func2() noexcept
V>{
V>  try {
V>    return func1();
V>  } catch (...) {
V>    static_assert(always_false<type_t>, "error!");
V>    return 0;
V>  }
V>}
V>

V>Так вот, стандартный подход с always_false тут не прокатывает и static_assert срабатывает всегда, а мне нужно что бы он срабатывал только если возникло исключение. Как такое можно организовать?

Интуиция подсказывает, что здесь можно как-то с пользой использовать атрибут assume, но что-то не соображу, как именно.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 21.12.24 15:03
Оценка:
Здравствуйте, rg45, Вы писали:

R>...


Делал именно таким методом, но было подумал, что занимаюсь извращением и как-то сложно получается. Вот решил спросить у более опытных коллег. Интересно имменно в рамках 20-го стандарта.
Тут масса вариавнов: можно через pair, можно через option, но в любом случае, приходится городить массу кода для преобразования типов исключений в сообщения об ошибках.
Отредактировано 21.12.2024 15:06 Videoman . Предыдущая версия .
Re[2]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 22.12.24 13:04
Оценка:
Здравствуйте, so5team, Вы писали:

S>А как в рамках C++20 (и даже C++23) бросить исключение в compile-time?


Также как с выделением памяти. Если весь процесс остается внутри и все сайд эффекты compile-time, но всё работает. Сама внешняя функция noexcept, наружу ничего не летит.
Re[4]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 22.12.24 20:11
Оценка:
Здравствуйте, so5team, Вы писали:

Ну запутали, так запутали!!!
Re[6]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 23.12.24 09:18
Оценка:
Здравствуйте, so5team, Вы писали:

S>Простите, не понял, что означает ваш ответ с фейспалмом.


Да я не вам вообще, я на ситуацию в общем.
Я только погружаюсь в 20-й стандарт. Просто задал вопрос, а вы мне в ответ тоже вопрос, да еще как-то неуверенно, может/не может кидать исключения
Из-за того, что не понятно сработают на этапе компиляции constexpr выражения или нет, у меня возникла путаница в коде в котором вперемешку constexpr/не constexpr реализация через std::is_constant_evaluated.
Теперь мне понятно как это работает:
в runtime версии возможно throw, а в constexpr — нет, но просто синтаксис try блоков теперь не отпугивает компилятор.

После паузы я и написал — как все запутано в стандарте.
Re[2]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 23.12.24 09:22
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Если не секрет, что именно стало удобно с появлением этой возможности?


Писать в одной функции две ветки кода, одна для вычисления на уровне компиляции, а другая в run-time.
Re[7]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 23.12.24 09:29
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Я только погружаюсь в 20-й стандарт. Просто задал вопрос, а вы мне в ответ тоже вопрос, да еще как-то неуверенно, может/не может кидать исключения


У меня у самого путаница в стандартах: в каких-то разрешили динамическую память в виде std::string (вроде бы в C++23), в каких-то вроде как и выброс исключений в compile-time разрешили (емнип, в C++26).

Поэтому если смотреть на самые свежие стандарты, то вроде как там можно столкнуться с проблемой, про которую вы спрашиваете. И может быть вы хотите сейчас, уже в рамках C++20 защититься о того, что добавили в С++26. Но проверить гипотетическое решение в рамках C++20 (и вроде бы даже в рамках C++23) не представляется возможным, т.к. в этих стандартах constexpr-функции не бросают исключений.

V>После паузы я и написал — как все запутано в стандарте.


Да не, вроде бы в конкретном стандарте все более-менее. А вот если пытаться прикидывать на перспективу, на тот же C++26, который когда-нибудь компиляторами будет поддержан, то да, становится запутанно.
Re[8]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 23.12.24 09:44
Оценка:
Здравствуйте, so5team, Вы писали:

S>Поэтому если смотреть на самые свежие стандарты, то вроде как там можно столкнуться с проблемой, про которую вы спрашиваете. И может быть вы хотите сейчас, уже в рамках C++20 защититься о того, что добавили в С++26. Но проверить гипотетическое решение в рамках C++20 (и вроде бы даже в рамках C++23) не представляется возможным, т.к. в этих стандартах constexpr-функции не бросают исключений.


Не, так далеко я не заглядываю. Действуем потихоньку, сначала 20-й, дальше посмотрим.
Для меня главные две фишки С++20 сейчас, это std::is_constant_evaluated() и concept`ы. Вот и возникают некоторые вопросы, возможно уже всем понятные, по мере переползания на новый стандарт.
А ваши контор-вопросы меня просто в тупик поставили и пришлось самому погружаться в тему и разбираться, поэтому и не смог ничего внятного ответить.
Re[9]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 23.12.24 09:46
Оценка:
Здравствуйте, Videoman, Вы писали:

V>А ваши контор-вопросы меня просто в тупик поставили и пришлось самому погружаться в тему и разбираться, поэтому и не смог ничего внятного ответить.


Значит все пошло на пользу
Re[3]: static_assert в catch секции
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 23.12.24 11:26
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Писать в одной функции две ветки кода, одна для вычисления на уровне компиляции, а другая в run-time.


Нынче считается, что это способствует ясности изложения кода?
Re[3]: static_assert в catch секции
От: rg45 СССР  
Дата: 23.12.24 11:39
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Писать в одной функции две ветки кода, одна для вычисления на уровне компиляции, а другая в run-time.


Я вот тоже не очень понимаю, какую пользу можно извлечь из возможности писать try-catch в constexpr функции. Что может бросить исключение из того, что допустимо использовать внутри функции? А если ничего не может, то зачем тогда try-catch?
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 23.12.24 11:45
Оценка:
Здравствуйте, rg45, Вы писали:

V>>Писать в одной функции две ветки кода, одна для вычисления на уровне компиляции, а другая в run-time.


R>Я вот тоже не очень понимаю, какую пользу можно извлечь из возможности писать try-catch в constexpr функции. Что может бросить исключение из того, что допустимо использовать внутри функции? А если ничего не может, то зачем тогда try-catch?


А возможен ли такой сценарий: у человека была обычная функция, которая содержала внутри себя try-catch, но которую хотелось иметь еще и в виде constexpr, но раньше нельзя было это делать, т.к. там были try-catch.

Грубо говоря, было:

template<typename T>
int f() {
  try {
    return T::some_func();
  }
  catch(...) {
    // Ну не шмогли, ну и ладно.
    return 0;
  }
}


Теперь такая возможность появляется (т.е. функцию f из примера выше можно объявить constexpr) но не хочется "проглатывать" исключения, если они происходят в compile-time.
Re[5]: static_assert в catch секции
От: rg45 СССР  
Дата: 23.12.24 11:48
Оценка:
Здравствуйте, so5team, Вы писали:

S>Грубо говоря, было:


S>
S>template<typename T>
S>int f() {
S>  try {
S>    return T::some_func();
S>  }
S>  catch(...) {
S>    // Ну не шмогли, ну и ладно.
S>    return 0;
S>  }
S>}
S>


S>Теперь такая возможность появляется (т.е. функцию f из примера выше можно объявить constexpr) но не хочется "проглатывать" исключения, если они происходят в compile-time.


Да, только в этом сценарии отсутсвует долгожданное "try-catch в constexpr функции"
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 23.12.2024 11:52 rg45 . Предыдущая версия .
Re[6]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 23.12.24 11:57
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, so5team, Вы писали:


S>>Грубо говоря, было:


S>>
S>>template<typename T>
S>>int f() {
S>>  try {
S>>    return T::some_func();
S>>  }
S>>  catch(...) {
S>>    // Ну не шмогли, ну и ладно.
S>>    return 0;
S>>  }
S>>}
S>>


S>>Теперь такая возможность появляется (т.е. функцию f из примера выше можно объявить constexpr) но не хочется "проглатывать" исключения, если они происходят в compile-time.


R>Да, только в этом сценарии отсутсвует долгожданное "try-catch в constexpr функции"


Почему отсутствует? Была просто f() показанная выше, стала:
template<typename T>
constexpr int f() {
  try {
    return T::some_func();
  }
  catch(...) {
    // Ну не шмогли, ну и ладно.
    return 0;
  }
}
Re[7]: static_assert в catch секции
От: rg45 СССР  
Дата: 23.12.24 12:05
Оценка:
Здравствуйте, so5team, Вы писали:

S>Почему отсутствует? Была просто f() показанная выше, стала:

S>
S>template<typename T>
S>constexpr int f() {
S>  try {
S>    return T::some_func();
S>  }
S>  catch(...) {
S>    // Ну не шмогли, ну и ладно.
S>    return 0;
S>  }
S>}
S>


Но в таком варианте выражение T::some_func() заведомо не может быть источником исключения, иначе это просто не скомпилируется (или я чего-то не знаю). Отсюда снова вопрос о ценности try-catch в constexpr функции. Вопрос же именно о ценности, а не о том, какова могла быть предыстория образования данного кода.
--
Справедливость выше закона. А человечность выше справедливости.
Re[9]: static_assert в catch секции
От: rg45 СССР  
Дата: 23.12.24 12:40
Оценка:
Здравствуйте, so5team, Вы писали:


S>Так там не зря же вызывается some_func из T. В зависимости от T это могут быть как some_func с исключениями внутри, так и без исключений.


Вот теперь вижу своё заблуждение. Таки может быть T::some_func() источником исключения: http://coliru.stacked-crooked.com/a/c4d662b12f9683eb
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 23.12.2024 17:55 rg45 . Предыдущая версия . Еще …
Отредактировано 23.12.2024 12:47 rg45 . Предыдущая версия .
Re[5]: static_assert в catch секции
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.12.24 10:39
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Теперь можно писать код, которые будет работать и в том и в том режиме.


Возможно, я что-то упускаю, но вся эта чехарда с constexpr/consteval больше похожа на поддержку очередного набора трюков, нежели на средства выражения замысла программиста.

Поскольку компилятор всегда видит все зависимости между данными, ему не требуется явного указания constexpr, чтобы вычислить при компиляции выражение, если оно технически вычислимо. Единственное, что здесь может быть полезно — это consteval/constinit, чтобы получить ошибку, если выражение не удается вычислить во время компиляции.

Соответственно, функция вроде Вашей сильно смахивает на дверь, в петлю которой вставлена дужка незапертого замка. То ли пытались запереть, но забыли или не сумели, то ли просто не нашлось ничего более подходящего, чтоб сама не распахивалась.
Re[6]: static_assert в catch секции
От: so5team https://stiffstream.com
Дата: 24.12.24 11:01
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

V>>Теперь можно писать код, которые будет работать и в том и в том режиме.


ЕМ>Возможно, я что-то упускаю, но вся эта чехарда с constexpr/consteval больше похожа на поддержку очередного набора трюков, нежели на средства выражения замысла программиста.


И?

Даже если вы и правы, то что следует? Следует перестать использовать constexpr/consteval? Следует написать пропозал об отмене constexpr/consteval и попробовать провести его через комитет, чтобы в C++29 и C++32 ключевые слова constexpr/consteval для функций/методов сделали опциональными?
Re[6]: static_assert в catch секции
От: Videoman Россия https://hts.tv/
Дата: 24.12.24 11:02
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Соответственно, функция вроде Вашей сильно смахивает на дверь, в петлю которой вставлена дужка незапертого замка. То ли пытались запереть, но забыли или не сумели, то ли просто не нашлось ничего более подходящего, чтоб сама не распахивалась.


Проблема не в том, что бы вычислять на этапе компиляции, а в том, что не хочется писать код отдельно для compile-time и отдельно для run-time. Представь, что 95% кода работает именно так, как ты говоришь, но где-то в потрохах вызывается функция, которая не может быть выполнена в compile-time. Теперь такое можно поддерживать, просто имея две реализации одной функции, имея остальной код в единственном экземпляре.
Re[7]: static_assert в catch секции
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.12.24 11:44
Оценка:
Здравствуйте, so5team, Вы писали:

S>Даже если вы и правы, то что следует?


Комитету следовало бы подумать перед тем, как. Теперь уже, конечно, этот хлам будут тащить и дальше.
Re[7]: static_assert в catch секции
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.12.24 11:46
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Теперь такое можно поддерживать, просто имея две реализации одной функции


Компилятор сам не хочет определять, вычислима ли функция с конкретными параметрами во время компиляции, и требует явного указания constexpr?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.