Является ли это соответствующим расширением компилятора для обработки стандартных библиотечных функций non-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, мы можем использовать их там, где требуется постоянное выражение как из черновика стандарта C++11, так и из черновика стандартного раздела C++14 7.1.5 [dcl.constexpr]:

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

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

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

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

1 ответ

TL;DR

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

подробности

Ответ на этот вопрос изменился с развитием статуса выпуска LWG 2013, который начинается с:

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

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

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

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

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

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

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

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

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

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

Обратите внимание, я добавил комментарий к сообщению об ошибке, объясняющий, что разрешение изменилось, так как эта проблема была первоначально решена.

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

Как насчет внутренних

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

static constexpr double a = __builtin_cos(3.);

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

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

Другие вопросы по тегам