Является ли это совместимым расширением компилятора для обработки стандартных библиотечных функций, отличных от constexpr, как constexpr?

gcc компилирует следующий код без предупреждения:

#include <cmath>

struct foo {
  static constexpr double a = std::cos(3.);
  static constexpr double c = std::exp(3.);
  static constexpr double d = std::log(3.);
  static constexpr double e1 = std::asin(1.);
  static constexpr double h = std::sqrt(.1);
  static constexpr double p = std::pow(1.3,-0.75);
};

int main()
{
}

Ни одна из стандартных функций библиотеки, используемых выше, не является функцией constexpr, нам разрешено использовать их там, где требуется постоянное выражение из проекта стандарта С++ 11 и черновик стандарта С++ 14 7.1.5 [dcl.constexpr]:

[...] Если он инициализирован вызовом конструктора, этот вызов должен быть постоянное выражение (5.19). В противном случае, или если спецификатор constexpr используется в описании ссылки, каждое полное выражение, которое появляется в его инициализатор должен быть постоянным выражением. [...]

Даже при использовании -std=c++14 -pedantic или -std=c++11 -pedantic никаких предупреждений не генерируется (см. его в прямом эфире). Использование -fno-builtin приводит к ошибкам (см. Его в прямом эфире), что указывает на то, что builtin версия этих стандартов библиотечные функции обрабатываются так, как если бы они были constexpr

Пока clang не позволяет использовать код с любой комбинацией флагов, которые я пробовал.

Итак, это расширение gcc для обработки хотя бы некоторых встроенных функций, как если бы они были функциями constexpr, даже если стандарт явно не требует их. Я ожидал бы, по крайней мере, получить предупреждение в режиме строгого соответствия, является ли это соответствующим расширением?

Ответы

Ответ 1

TL; DR

В С++ 14 это явно не разрешено, хотя в 2011 оно выглядело так, как будто этот случай явно разрешен. Неясно, что для С++ 11 это подпадает под правило as-if, я не верю, что это происходит, поскольку оно изменяет наблюдаемое поведение но этот вопрос не был уточнен в проблеме, о которой я упоминал ниже.

Подробнее

Ответ на этот вопрос изменился с меняющимся статусом LWG issue 2013, который открывается с помощью

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

В С++ 11 было неясно, разрешило ли это правило as-if это, но предложение orignal явно разрешило его после его принятия, и мы можем видеть ниже в отчете об ошибке gcc, на который ссылаюсь, это было сделано командой gcc.

Консенсус, позволяющий это изменить в 2012 году, и предложение изменилось, а в С++ 14 это несоответствующее расширение. Это отражено в стандартном разделе проекта С++ 14 17.6.5.6 [constexpr.functions], который гласит:

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

и хотя строгое чтение этого, похоже, оставляет некоторое пространство для маневра для обработки встроенного неявно, как если бы это было constexpr, мы можем видеть из следующей цитаты в этом вопросе, что целью было предотвращение расхождения в реализациях, поскольку идентичный код мог вызывают различное поведение при использовании SFINAE (основное внимание):

Некоторая озабоченность, выраженная при представлении полного комитета для голосования к статусу WP, что этот вопрос был разрешен без достаточного думал о последствиях для расходящихся реализаций библиотек, поскольку пользователи могут использовать SFINAE для наблюдения за другим поведением в противном случае идентичный код.

Из отчета gcc bug [С++ 0x] sinh vs asinh vs constexpr видно, что команда полагалась на ранее предложенную разрешение LWG 2013, в котором говорится:

[...] Кроме того, реализация может объявить любую функцию constexpr, если это определение функции удовлетворяет ограничения [...]

при решении вопроса о том, разрешено ли это изменение для математических функций в режиме строгого соответствия.

Насколько я могу судить, это станет соответствовать, если это мы получили предупреждение в строгом режиме соответствия, то есть с помощью -std=c++11 -pedantic или если он был отключен в этом режиме.

Заметьте, я добавил комментарий к отчету об ошибке, пояснив, что разрешение изменилось с тех пор, как эта проблема была первоначально исправлена.

Джонатан Вакели указал на в другом вопросе более поздний обсуждение, и он кажется вероятным, что отчет об ошибке gcc будет вновь открыт для решения этой проблемы соответствия.

Как насчет встроенных функций

Внутренние параметры компилятора не охватываются стандартом, и насколько я могу судить, они должны быть освобождены от этого правила, поэтому используйте:

static constexpr double a = __builtin_cos(3.);

должно быть разрешено. Этот вопрос возник в отчете об ошибке, и мнение Дэниела Крюглера было:

[...] Функции библиотеки и другие внутренние функции, вероятно, можно рассматривать как исключений, поскольку они не обязаны быть "объяснимыми" посредством нормальные языковые правила.