Является ли компилятор допустимым в отношении поведения undefined в постоянном выражении?
Мы знаем, что операции которые вызывают поведение undefined, не являются основными константными выражениями (раздел 5.19 параграфа 2 из черновик стандарта С++)
В тестах я выполнял как clang
, так и gcc
поведение undefined в constexpr как ошибку, но они несовместимы в случае сдвига вправо влево. Например, во всех этих случаях, которые рассматриваются как поведение undefined в соответствии с разделом 5.8
Операторы сдвига с 1 по 3:
constexpr int x1 = 1 << 33 ; //Assuming 32-bit int
constexpr int x2 = 1 << -1 ;
constexpr int x3 = -1 << 1 ;
constexpr int x4 = 1 >> 33 ; //Assuming 32-bit int
constexpr int x5 = 1 >> -1 ;
clang
приведет к ошибке (увидеть его в прямом эфире):
error: constexpr variable 'x1' must be initialized by a constant expression
constexpr int x1 = 1 << 33 ; //Assuming 32-bit int
^ ~~~~~~~
note: shift count 33 >= width of type 'int' (32 bits)
constexpr int x1 = 1 << 33 ; //Assuming 32-bit int
....
while gcc
выдаст предупреждение, но все равно будет считать, что каждая переменная является постоянным выражением (видеть ее в прямом эфире):
warning: left shift count >= width of type [enabled by default]
constexpr int x1 = 1 << 33 ; //Assuming 32-bit int
^
warning: left shift count is negative [enabled by default]
constexpr int x2 = 1 << -1 ;
...
Это выглядит как ошибка gcc
, но я знаю, что компилятор может сделать более сильные гарантии для поведения, который, по словам стандарта, undefined, и он выглядит как gcc дает более сильные гарантии для смены. Это может оказаться ошибкой, но это заставляет меня задаться вопросом, разрешил ли компилятор тот же доступ в контексте constexpr
, или компилятор должен строго придерживаться того, что говорит стандарт, - это поведение undefined здесь?
Обновить
Как упоминает Алан, действительно верно, что диагностика плохо сформированной программы может быть либо ошибкой, либо предупреждением, но в этом случае gcc
, похоже, не считает программу плохо сформированной. В отличие от других экземпляров, например, в случае overflow, gcc
не жалуется на недопустимый constexpr, но предупреждает о смене. Таким образом, казалось бы, либо это ошибка, либо gcc
не рассматривает эти случаи как undefined и, следовательно, мой вопрос.
Ответы
Ответ 1
Поскольку Йоханнес, похоже, не хочет преобразовать свой комментарий в ответ, тогда я сам отвечу. У меня был автономный разговор с Howard Hinnant, и он подтвердил консенсус в комментариях о том, что поведение gccs
в этом контексте действительно соответствует.
Соответствующим разделом из проекта стандарта будет раздел 1.4
Соответствие реализации, которое гласит в пункте 2:
Хотя в этом международном стандарте указаны только требования к реализациям на С++, эти требования часто легче понять, если они сформулированы как требования к программам, частям программ или выполнению программ. Такие требования имеют следующее значение:
и имеет следующую пулю (выделение мое):
Если программа содержит нарушение любого диагностируемого правила или появление конструкции, описанной в этом стандарте, как "условно-поддерживаемая", когда реализация не поддерживает эту конструкцию, соответствующая реализация должна выдать хотя бы одну диагностику сообщение.
Диагностика может быть предупреждением или ошибкой. Поэтому, когда gcc
предоставляет предупреждение о поведении undefined, это не требует последующего предупреждения о самом constexpr.
Хотя это соответствует поведению, порождающему ошибку для constexpr и позволяющее SFINAE казаться более надежным. Учитывая, что gcc
выдает ошибки в других экземплярах поведения undefined в constexpr, это не похоже на предполагаемое поведение или если это было, по крайней мере, непоследовательное поведение, поэтому я отправил отчет об ошибке.