const int forty_two = two_i - four;

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

• Задание границ массива:

int bounds = 99;   │Ошибка, bounds — не константное

int array[bounds];←┘выражение

const int bounds2 = 99;│Правильно, bounds2 — константное

int array2[bounds2];  ←┘выражение

• Задание значения параметра шаблона, не являющего типом:

template

struct test {};  │Ошибка, bounds —

                 │не константное

test is;←┘выражение

test ia2;←┐Правильно, bounds2 —

                    │константное выражение

• Задание непосредственно в определении класса инициализатора для переменной-члена класса целочисленного типа со спецификаторами static const:

class X {

 static const int the_answer = forty_two;

};

• Употребление в инициализаторах встроенных типов или агрегатов, применяемых для статической инициализации:

struct my_aggregate {

 int a;

 int b;

};

static my_aggregate ma1 =│Статическая

 { forty_two, 123 };    ←┘инициализация

int dummy = 257;                          │Динамическая

static my_aggregate ma2 = {dummy, dummy};←┘инициализация

Такая статическая инициализация полезна для предотвращения зависимости от порядка инициализации и состояний гонки.

Всё это не ново и было описано еще в стандарте С++ 1998 года. Но в новом стандарте появилось и дополнение в части константных выражений — ключевое слово constexpr.

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

constexpr int square(int x) {

 return x*x;

}

int array[square(5)];

В этом случае массив array будет содержать 25 значений, потому что функция square объявлена как constexpr. Конечно, из того, что функцию можно использовать в константном выражении, еще не следует, что любой случай ее использования автоматически будет константным выражением:

int dummy = 4;           (1) Ошибка, dummy — не константное

int array[square(dummy)];←┘выражение

В этом примере dummy не является константным выражением (1), поэтому не является таковым и square(dummy). Это обычный вызов функции, и, следовательно, для задания границ массива array его использовать нельзя.

<p>А.4.1. <code>constexpr</code> и определенные пользователем типы</p>

До сих пор мы употребляли в примерах только встроенные типы — такие, как int. Но в новом стандарте С++ допускаются константные выражения любого типа, удовлетворяющего требованиям, предъявляемым к литеральному типу. Чтобы тип класса можно было считать литеральным, должны быть выполнены все следующие условия:

• в классе должен существовать тривиальный копирующий конструктор;

• в классе должен существовать тривиальный деструктор;

• все нестатические переменные-члены данного класса и его базовых классов должны иметь тривиальный тип;

• в классе должен существовать либо тривиальный конструктор по умолчанию, либо constexpr-конструктор, отличный от копирующего конструктора.

О constexpr-конструкторах мы поговорим чуть ниже. А пока обратимся к классам с тривиальным конструктором по умолчанию. Пример такого класса приведён ниже:

class CX {

private:

 int а;

 int b;

public:

 CX() = default; ←(1)

 CX(int a_, int b_) : ←(2)

  a(a_), b(b_) {}

 int get_a() const {

  return a;

 }

 int get_b() const {

  return b;

 }

 int foo() const {

  return a + b;

 }

};

Здесь мы явно объявили конструктор по умолчанию (1) умалчиваемым (см. раздел А.3), чтобы сохранить его тривиальность, несмотря на наличие определённого пользователем конструктора (2). Таким образом, этот тип удовлетворяет всем требованиям к литеральному типу и, значит, его можно использовать в константных выражениях. К примеру, можно написать constexpr-функцию, которая создает новые экземпляры этого класса:

constexpr CX create_cx() {

Перейти на страницу:

Похожие книги