Почему я могу вызвать функцию не-constexpr внутри функции constexpr?

Рассмотрим следующий код:

#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?

16

Решение

Программа плохо формируется и не требует диагностики в соответствии с Проект стандарта 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 если явно не разрешено стандартом.

11

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]