constexpr неопределенное поведение - PullRequest
18 голосов
/ 14 сентября 2011

Я экспериментировал с 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();
}

Ответы [ 2 ]

11 голосов
/ 15 сентября 2011

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

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

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

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

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

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

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

5 голосов
/ 24 января 2014

Да, компилятор должен отлавливать это во время компиляции, если мы посмотрим на раздел 5.19 Выражения констант параграф 2 черновика стандарта C ++ это перечисляет это как исключение для константных выражений:

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

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

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

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

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