Как инициализировать ссылку constexpr

Я пытаюсь инициализировать ссылку constexpr без успеха. Я попробовал

#include <iostream>

constexpr int& f(int& x) // can define functions returning constexpr references
{
    return x;
}

int main()
{
    constexpr int x{20};
    constexpr const int& z = x; // error here
}

но я получаю ошибку времени компиляции

error: константа constexpr 'z' должна быть инициализирована константным выражением

Удаление const приводит к

error: привязка ссылки к типу 'int' к значению типа 'const int' drop qualifiers

хотя у меня было ощущение, что constexpr автоматически подразумевает const для объявлений переменных.

Итак, мои вопросы:

  • Полезны ли ссылки constexpr? (то есть "лучше", чем const ссылки)
  • Если да, как я могу их эффективно определить?

PS: Я видел пару вопросов, связанных с моим, например Какие значения могут быть присвоены ссылке` constexpr`?, но я не знаю, Думаю, они решают мои вопросы.

Ответы

Ответ 1

  • Являются ли ссылки на constexpr полезными? (то есть, "лучше", чем ссылки на константу)

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

  1. Если да, как я могу их эффективно определить?

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

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

Ответ 2

Таким образом, проблема заключается в том, что ссылка constexpr должна связываться с объектом со статической продолжительностью хранения, которая рассматривается в проекте С++ 11: N3337 раздел 5.19 [expr.const] (основное внимание):

Ссылочное постоянное выражение является значением lvalue ядро константное выражение, которое обозначает объект со статической продолжительностью хранения или функцией

черновик стандарта С++ 14: N3936 изменяет формулировку:

Постоянное выражение представляет собой либо выражение константы ядра glvalue, значение которого относится к объекту со статическим время хранения или функцию, или константное выражение основного значения prvalue, значение которого является объектом, где для этот объект и его подобъекты:

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

Таким образом, изменение объявления x будет таким: [/p >

constexpr static int x{20};

Ответ 3

Как и T.C., инициализатор должен быть объектом со статической продолжительностью хранения.

N4140/§5.19/4 Постоянным выражением является либо ядро ​​glvalue постоянное выражение, значение которого относится к объекту со статическим время хранения [...]

N4140/§7.1.5/9 Спецификатор constexpr, используемый в объявлении объекта объявляет объект как const. Такой объект должен иметь буквальный тип и должны быть инициализированы. [...] В противном случае, или если constexprспецификатор используется в декларации ссылок, каждое полное выражение которое появляется в его инициализаторе, должно быть постоянным выражением.

В N3337 формулировка отличается.