Может ли основное константное выражение содержать игнорируемое reinterpret_cast? - PullRequest
0 голосов
/ 29 февраля 2020

При компиляции следующей программы-примера с онлайн-компилятором godbolt.org Clang-9.0.0 и MSV C v19.24 сообщают об ошибках в строках, отмеченных (1) и (2). Сообщение об ошибке говорит, что выражение (reinterpret_cast<uintptr_t>(&x), 1) не оценивается как константа. Но это так, не правда ли?

G CC -9.2, с другой стороны, компилирует этот образец без ошибок.

#include <memory>

int x;

enum
{
    Value = (reinterpret_cast<uintptr_t>(&x), 1)    // (1)
};

template <int N>
struct Test
{
};

Test<(reinterpret_cast<uintptr_t>(&x), 1)>     t;   // (2)

Вопрос: действительно ли (reinterpret_cast<uintptr_t>(&x), 1) оценить до константы?

1 Ответ

7 голосов
/ 29 февраля 2020

Выражение константы ядра не может содержать reinterpret_cast, даже если его значение отбрасывается (поэтому MSV C и Clang вправе отклонить код). См. C ++ 17 [expr.const] /2.15:

Выражение e является выражением основной константы, если только оценка e, следуя правилам абстрактной машины, не будет одно из следующих выражений: ... a reinterpret_cast

Согласно правилам абстрактной машины, reinterpret_cast должен быть оценен. См. [Expr.comma] / 1:

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

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

Это отличается от ситуаций, когда актерский состав действительно не оценивается:

enum {
    Value = 1 || reinterpret_cast<uintptr_t>(&x);  // OK
}
...