Как сказать static_assert, что аргументы функции constexpr являются постоянными?

У меня есть функция constexpr, которая выглядит примерно так:

constexpr int foo(int bar)
{
   static_assert(bar>arbitrary_number, "Use a lower number please");

   return something_const;
}

Тем не менее, сборка этого с GCC 4.6.3 продолжает говорить мне

ошибка: "бар" не может появляться в константном выражении

Я пробовал что-то вроде

constexpr int foo(constexpr const int bar)
{
   static_assert(bar>arbitrary_number, "Use a lower number please");

   return something_const;
}

но constexpr не может использоваться для аргументов функции.

Есть ли какой-нибудь простой способ сообщить компилятору, что bar всегда является постоянной времени компиляции?

3 ответа

Решение

Есть ли какой-нибудь простой способ сообщить компилятору, что bar всегда является постоянной времени компиляции?

Если bar всегда константа времени компиляции, тогда вы должны написать свою функцию как:

template<int bar>
constexpr int foo()
{
   static_assert(bar>arbitrary_number, "Use a lower number please");
   return something_const;
}

Потому что, если вы этого не сделаете, а вместо этого напишите то, что уже написали, то в этом случае функцию также можно вызывать с неконстантным аргументом; просто если вы передадите неконстантный аргумент, функция потеряет свою запутанность.

Обратите внимание, что в приведенном выше коде arbitrary_number также должно быть константным выражением, иначе оно не будет компилироваться.

constexpr функции могут быть оценены во время компиляции, это не предписывается стандартом в целом (вы можете заставить функцию быть оцененной во время компиляции, используя ее внутри константного выражения, как инициализация constexpr переменная с ним).

Кроме того, аргументы constexpr функции на самом деле не являются постоянными, они могут меняться при каждом вызове (даже если оцениваются во время компиляции)

Обходной путь - использовать нетипичный шаблон для передачи bar, если это всегда постоянная времени компиляции (что кажется).

foo может использоваться следующим образом:

int i;
std::cin >> i;
foo("foo", i);

Как вы видете i не является константным выражением выше, но оно все еще может быть использовано с constexpr функции. constexpr функции (и шаблоны функций) - странный зверь, который гарантирует, что, например, foo(p, i) константное выражение, если p а также i также есть, но все еще может использоваться как обычные функции.

Если аргументы ваших функций действительно должны всегда быть константными выражениями, то они должны быть аргументами шаблона, а не аргументами функции.

Другие вопросы по тегам