Следующая программа была сокращена, чтобы продемонстрировать вопрос. struct A
имеет функцию-член constexpr
, которая сравнивает this
с некоторым указателем, которым может быть nullptr
. Затем эта функция-член вызывается для временного объекта (принимая адрес rvalue) внутри постоянного выражения:
struct A {
A * a = nullptr; // in real program this pointer can be changed
constexpr bool f() {
return a != this;
}
};
static_assert( A{}.f() );
Clang и MSVC с этим согласны, но GCC не нравится этот код, и он жалуется:
<source>:8:21: error: non-constant condition for static assertion
8 | static_assert( A{}.f() );
| ~~~~~^~
<source>:4:18: error: '((&<anonymous>) != 0)' is not a constant expression
4 | return a != this;
Онлайн-демо: https://gcc.godbolt.org/z/evK1Y1r8e
Это хорошо составленная программа? Или перед сравнением в константном выражении всегда необходимо проверять, чтобы указатели не были nullptr
?
Нет это не так. A* a
можно изменить во время выполнения, поэтому это не постоянное выражение, и поэтому его нельзя использовать в функции constexpr. Если бы A* можно было вычислить во время компиляции, это было бы static constexpe A* a = ...
@PepijnKramer Конкретный объект A
, который здесь рассматривается, является временным, существующим только во время оценки операнда static_assert
. Его член a
не может быть изменен во время выполнения. Так что с этим нет проблем.
@ user4581301 См. выше.
@user17732522 user17732522 Здесь рассматривается, да. Меня беспокоит реальный случай. Показанный здесь пример слишком упрощает и больше не представляет истинную проблему?
Это всего лишь ошибка GCC: конечно, этому вычислению известен (символический) адрес временного объекта, созданного во время постоянной оценки.
in real program this pointer can be changed
предполагает, что сравнения может быть недостаточноconst
для времени компиляции. При каких обстоятельствах значениеa
может быть изменено? Все ли они компилируются только во время?