Константные выражения

В Ü существуют выражения, называемые константными, чьё значение может быть вычислено на этапе сборки программы. Такие выражения могут быть применены в ряде мест, где это требуется - в размерах типов массивов, в параметрах шаблонов, в конструкциях static_assert и static_if.

Выражение является константным, если:

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

«constexpr» типы

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

constexpr типами являются:

  • все фундаментальные типы
  • все перечисления
  • все указатели на функции
  • массивы с типами элементов, являющимися constexpr
  • кортежи с типами элементов, являющимися constexpr
  • некоторые типы структур

Требования к constexpr структурам:

  • типы всех полей должны быть constexpr
  • они не должны иметь изменяемых (mut) ссылочных полей
  • они не должны иметь явно обозначенных конструкторов копирования, копирующих операторов присваивания, деструкторов

«constexpr» функции

Функции, которые могут быть использованы в константных выражениях, должны быть явно помечены с использованием ключевого слова constexpr. Такие функции должны иметь тело тут-же, не допускается объявление constexpr для прототипа функции.

Требования к constexpr функциям:

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

constexpr функции могут иметь изменяемые ссылочные аргументы, но такие функции нельзя позвать для constexpr аргументов. В constexpr функциях дозволены все остальные конструкции, кроме запрещённых, в т. ч. циклы, условия, halt и т. д.

Пример constexpr функции:

fn constexpr ArrSumm( [ u32, 16 ]& arr ) : u32
{
    auto mut res= 0u;
    auto mut i= 0s;
    while( i < 16s )
    {
        res+= arr[i];
        ++i;
    }
    return res;
}

«constexpr» переменные

Неизменяемые переменные с constexpr типом и константно-инициализированные являются константными. Если необходимо удостовериться в константности переменной, её следует объявить с модофикатором изменяемости constexpr.

auto x= 0; // Переменная неявно объявлена как неизменяемая, инициализатор является константным, как следствие, переменная будет константной
auto imut y= x + 5; // Аналогично, но на сей раз переменная объявлено неизменяемой явно
var i32 z(66), imut v(-5), w= y / 2; // все эти переменные будут константными
var [ i32, 2 ] arr[ 0 + z, w * 10 ]; // и эти тоже
auto constexpr x_copy= x; // явно требуем константности
var i32 constexpr ensure_constant(y); // явно требуем константности

var i32 mut nonconst= 0; // хоть инициализатор и константный, переменная константной не будет
auto constexpr wtf= nonconst; // будет порождена ошибка - инициализатор переменной неконстантен