Почему не abs constexpr?

В <cinttypes>, поскольку С++ 11, следующие две перегрузки:

std::intmax_t abs( std::intmax_t n );
std::intmax_t imaxabs( std::intmax_t n );

Почему не эти две функции constexpr?

Ответ 1

Я не могу объяснить, почему abs не может быть constexpr и, по-видимому, не может gcc. Когда я использую gcc 4.9.2 с этой программой:

#include <cstdlib>
#include <cinttypes>
#include <cassert>

constexpr intmax_t abs3 = std::abs(3);
constexpr intmax_t absneg3 = std::abs(-3);
int main()
{
    assert(abs3 == absneg3);
}

он компилируется и запускается до завершения без предупреждений или ошибок. Вы можете попробовать здесь. Однако clang++ (версия 3.5.0) генерирует ошибку времени компиляции:

abs.cpp: 6: 20: ошибка: constexpr переменная 'abs3' должна быть инициализирована константным выражением.

Я думаю, что clang++ действительно получает это прямо здесь, потому что в разделе 27.9.2 [c.files] стандарта 2011 года говорится:

Содержимое заголовка совпадает с заголовком стандартной библиотеки C со следующими изменениями:

- заголовок содержит заголовок вместо, и

- тогда и только тогда, когда тип intmax_t обозначает расширенный целочисленный тип (3.9.1), следующая функция добавляются подписи:

intmax_t abs (intmax_t);

imaxdiv_t div (intmax_t, intmax_t);

который должен иметь ту же семантику, что и сигнатуры функции intmax_t imaxabs (intmax_t) и imaxdiv_t imaxdiv (intmax_t, intmax_t) соответственно.

В текущий рабочий проект стандарта С++, как и в опубликованной версии 2014 года, говорится в разделе 17.6.5.6 [constexpr.functions ]:

Этот стандарт явно требует, чтобы определенные стандартные библиотечные функции были constexpr (7.1.5). Реализация не должна объявлять какую-либо стандартную подпись функции библиотеки как constexpr, за исключением тех, где она явно требуется.

Итак, на данный момент результат состоит в том, что эти функции по-прежнему не соответствуют constexpr в соответствии со стандартом (который вы знали), но они могут быть, как продемонстрировано компилятором gcc.

Ответ 2

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

Обновление стандарта - это процесс, включающий человеческие усилия по предложению изменений и их рассмотрение и принятие. А это означает, что при добавлении новой функции - и constexpr - это новая функция, а не все остальное автоматически обновляется для использования этой функции. Этот конкретный случай вполне может быть обновлен в будущей эволюции стандарта - если некоторые люди возьмут на себя часто неблагодарную задачу предложить набор изменений, некоторые другие люди возьмут на себя задачу его рассмотрения и убедят тех, кто имеет право голоса на комитет, чтобы принять его.