объект, возвращающий объект conteval с нетривиальным деструктором constexpr - PullRequest
6 голосов
/ 14 октября 2019

C ++ 20 будет иметь новое ключевое слово consteval и деструктор constexpr , если все пойдет хорошо. к сожалению, на данный момент нет компилятора, который я знаю о consteval . следующий код будет действительным.

struct A {
  constexpr ~A() {}
};

consteval A f() {
    return A{};
}

void test() {
    A a;
    a = f(); // <-- here
}

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

я не нашел ни одной цитаты из статей consteval и constexpr destructor , которые явно запрещают это. но я не вижу, как это может быть правильно.

будет ли следующий код действительным в C ++ 20? что должно произойти с этим кодом?


Примечание:

в конвертной бумаге приведен этот пример. здесь функция conteval вызывается вне постоянного контекста.

consteval int sqr(int n) {
  return n*n;
}
constexpr int r = sqr(100);  // Okay.
int x = 100;
int r2 = sqr(x);  // Error: Call does not produce a constant.

1 Ответ

3 голосов
/ 14 октября 2019

Я думаю, что этот код в порядке.

Существенным аспектом consteval является [expr.const] / 12 :

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

In

void test() {
    A a;
    a = f(); // <-- here
}

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

Примечание: просто f(), а не a = f();, здесь не требуется, чтобы оператор присваивания был константным выражением.

Все, что вызывает f(), прекрасно. Все специальные функции-члены A доступны в течение постоянного времени оценки. Результат f() является допустимым результатом константного выражения ( [expr.const] / 10 ) аналогичным образом, поскольку оно также не вызывает каких-либо ограничений там (A не имеет указателя или ссылкичлены, так что, как правило, ни один из них не ссылается на объекты без статической длительности хранения).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...