Подтвердить что ты не робот

Constexpr undefined поведение

Я экспериментировал с constexpr. В моем тестовом компиляторе (g++ 4.6) это не удается скомпилировать с ошибкой об отсутствии доступа к границам. Требуется ли компилятор определить это во время компиляции?

#include <iostream>

constexpr const char *str = "hi";

constexpr int fail() {
  return str[1000]; // Way past the end!
}

template <int N>
struct foo {
  static void print() { std::cout << N << std::endl; }
};

int main() {  
  foo<fail()>::print();
}
4b9b3361

Ответ 1

§5.19/2 (на второй странице он действительно должен быть разделен на многие абзацы) запрещает константные выражения, содержащие

- преобразование lvalue-to-rvalue (4.1), если оно не применяется к

  

- значение целочисленного или перечисляемого типа, которое относится к энергонезависимому объекту const с предшествующей инициализацией, инициализированным константным выражением или

         

- значение glvalline типа, которое относится к энергонезависимому объекту, определенному с помощью constexpr, или относится к под-объекту такого объекта

  

str[1000] преобразуется в * ( str + 1000 ), который не относится к подобъекту str, в отличие от доступа к массиву in-bounds. Таким образом, это диагностическое правило, и компилятор должен жаловаться.

РЕДАКТИРОВАТЬ: Кажется, что есть некоторая путаница в том, как этот диагноз возникает. Компилятор проверяет выражение против §5.19, когда он должен быть постоянным. Если выражение не удовлетворяет требованиям, компилятор должен жаловаться. По сути, требуется проверить постоянные выражения на все, что могло бы в противном случае вызывать поведение undefined. * Это может включать или не включать попытку оценить выражение.

* В С++ 11, "результат, который не определен математически". В С++ 14 "операция, которая имела бы поведение undefined", которая по определению (§1.3.24) игнорирует поведение, которое реализация может определить как резерв.

Ответ 2

Да, компилятор должен поймать это во время компиляции, если мы посмотрим на раздел 5.19 Пояснения констант, абзац 2 черновик С++ standard он указывает это как исключение для постоянных выражений:

- операция, которая имела бы поведение undefined [Примечание: включая, например, целочисленное переполнение цепочки (раздел 5), определенную арифметику указателя (5.7), деление на ноль (5.6), или некоторые операции сдвига (5.8) -end note];

и issue 695, насколько я могу судить, говорит, что поведение undefined не является константой и должно выдавать диагностику:

Консенсус КСР заключался в том, что выражение, подобное 1/0, должно просто считаться непостоянным; любая диагностика может возникнуть в результате использования выражения в контексте, требующем постоянного выражения.

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