Рассмотрим следующий код:
#include <stdio.h>
constexpr int f()
{
return printf("a side effect!\n");
}
int main()
{
char a[f()];
printf("%zd\n", sizeof a);
}
Я бы ожидал, что компилятор будет жаловаться на вызов printf
внутри f
, так как f
должен быть constexpr
, но printf
не является. Почему программа скомпилируйте и распечатайте 15?
Программа плохо формируется и не требует диагностики в соответствии с Проект стандарта 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
и раздел 5.19
параграф 2 говорит:
Условное выражение является основным константным выражением, если оно
включает в себя одно из следующего в качестве потенциально оцениваемого подвыражения
[…]
и включает в себя:
— вызов функции, отличной от конструктора 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 если явно не разрешено стандартом.
Других решений пока нет …