Программа имеет неправильный формат и не требует диагностики в соответствии с проект стандарта C++11, раздел 7.1.5
Спецификатор constexpr, параграф 5, в котором говорится:
Для функции constexpr, если не существует таких значений аргументов функции, при которых подстановка вызова функции приводила бы к константному выражению (5.19), программа является некорректной; диагностика не требуется.
и приводит следующий пример:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
и параграф 2 раздела 5.19
гласит:
Условное-выражение является основным константным выражением, если только оно не включает одно из следующего в качестве потенциально оцениваемого подвыражения [...]
и включает:
— вызов функции, отличной от конструктора constexpr для литерального класса или функции constexpr [Примечание: разрешение перегрузки (13.3) применяется как обычно — примечание в конце];
Мы, вероятно, предпочли бы диагностику в этом случае, это может быть просто оплошность, у меня есть отчет об ошибке для аналогичной ситуации, когда gcc
не выдает ошибку, но мы, вероятно, хотели бы, чтобы она: Разрешена ли компилятору свобода действий в том, что он считает неопределенным поведением в постоянное выражение?.
Обновить
Использование флага -fno-builtin
приведет к тому, что gcc
выдаст следующую ошибку:
error: call to non-constexpr function 'int printf(const char*, ...)'
return printf("a side effect!\n");
^
Таким образом, gcc
считает это неправильным, он просто игнорирует его, когда использует встроенную версию printf
.
Хотя несколько непоследовательно использование -pedantic
приводит к следующему предупреждению:
warning: ISO C++ forbids variable length array 'a' [-Wvla]
char a[f()];
^
Обратите внимание, что использование f()
для инициализации переменной constexpr:
constexpr int x = f() ;
выдает ошибку:
error: 'printf(((const char*)"a side effect!\012"))' is not a constant expression
Обратите внимание, что в более общем случае компилятору не разрешается помечать стандартные библиотечные функции как constexpr , если это явно не разрешено стандарт.
person
Shafik Yaghmour
schedule
04.03.2014
3.5
выдает ошибку:note: non-constexpr function 'printf' cannot be used in a constant expression
- person Shafik Yaghmour   schedule 04.03.2014error: ISO C++ forbids variable length array 'a' [-Wvla]
- person juanchopanza   schedule 04.03.2014-pedantic
выдает ошибку. Судя по всему, gcc рассматривает это как VLA и никогда не пытается проверить, действительно ли этоconstexpr
. Попытка использоватьf()
в качестве аргумента шаблона, отличного от типа, завершится ошибкой. - person pmr   schedule 04.03.2014constexpr
. Затем он жалуется на VLA, потому что это то, что он поддерживает по умолчанию. - person juanchopanza   schedule 04.03.2014constexpr
: (а) всегда, как это делает clang, (б) когда требуется его оценка во время компиляции? - person pmr   schedule 04.03.2014clang
, кажется, очень хочет отклонить это, и это, вероятно, должно быть предупреждением, а не ошибкой. Это должно быть ошибкой, когдаf()
используется какconstexpr
. К сожалению, я не могу легко подтвердить это цитатой. - person pmr   schedule 04.03.2014f()
допустим в контексте, отличном от constexpr. Я должен проверить это, хотя. - person juanchopanza   schedule 04.03.2014printf
вызовомint foo() {return 42;}
, он не скомпилируется. То же самое следует сделать сprintf
, потому чтоconstexpr
тоже. - person juanchopanza   schedule 04.03.2014strlen
в GCC для символьного литерала равноconstexpr
, а GCC заменяетprintf
наputs
(илиputs
+strlen
, если вы используете возвращаемое значение), если строка формата не содержит спецификаторов формата. Таким образом, помимо очевидного побочного эффекта, можно было поверить, что это очень хорошаяconstexpr
функция. - person Damon   schedule 04.03.2014constexpr int x = f();
вgcc
, это выдает ошибку. - person Shafik Yaghmour   schedule 04.03.2014constexpr int x = strlen("foo");
прекрасно компилируется, и если вы разберете бинарный файл, вы нигде не найдете ни одного вызоваstrlen
, только литерал (при условии, что вы его используете, поэтому он не оптимизирован). По иронии судьбы, это не верно для встроенных макросов, таких как__func__
, которые для нас с вами совершенно очевидно являютсяconstexpr
, но компилятор будет утверждать, что это не так. - person Damon   schedule 04.03.2014-fno-builtin
, все это становится ошибками вgcc
. Так что это имеет больше смысла, я все еще думаю, что компилятору не разрешено это делать. - person Shafik Yaghmour   schedule 04.03.2014gcc
делать это или нет. - person Shafik Yaghmour   schedule 05.03.2014std::array<int, f()> a;
для проверки константных выражений, а не VLA. Пример - person   schedule 05.03.2014