Подтвердить что ты не робот

Std:: max() и std:: min() not constexpr

Я только заметил, что новый стандарт определяет min(a,b) и max(a,b) без constexpr.

Примеры из 25.4.7, [alg.min.max]:

template<class T> const T& min(const T& a, const T& b);
template<class T> T min(initializer_list<T> t);

Разве это не жалость? Мне бы хотелось написать

char data[ max(sizeof(A),sizeof(B)) ];

вместо

char data[ sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B) ];
char data[ MAX(sizeof(A),sizeof(B)) ]; // using a macro

Любая причина, по которой эти не могут быть constexpr?

4b9b3361

Ответ 1

Критическое обновление

Следующий анализ ошибочен, потому что он смущает одну важную вещь. В следующем утверждении я пропустил одну важную деталь, которая требует совершенно другого ответа.

Возврат без названия max будет ссылаться на этот операнд.

Проблема здесь в том, что подстановка функции вызывает done. Если подозрительная функция invocation будет включать в себя преобразование lvalue для rvalue для этого значения gl, которое max дает, все будет хорошо, потому что чтение из glvalue, которое ссылается на временную не статическую длительность хранения, является прекрасным при вычислении константного выражения. Но так как чтение происходит вне подстановки функции invocation, результатом замены функции является lvalue. Соответствующий текст спецификации говорит

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

Но ссылка, возвращаемая max, дает значение l, которое обозначает объект неопределенной продолжительности хранения. Требуется подстановка функции вызова, чтобы получить постоянное выражение, а не просто выражение постоянной константы. Поэтому max(sizeof(A), sizeof(B)) не гарантируется.

Следующий (более старый) текст необходимо прочитать, учитывая приведенное выше..


В настоящий момент я не вижу никакой причины, почему вы не захотите придерживаться constexpr там. В любом случае, следующий код определенно полезен

template<typename T> constexpr
T const& max(T const& a, T const& b) {
  return a > b ? a : b;
}

Вопреки тому, что пишут другие ответы, я думаю, что это законно. Не все экземпляры max должны быть constexpr-функциями. Текущий n3242 говорит

Если специализированная специализация шаблона функции constexpr или функция-член шаблона класса не будет удовлетворять требованиям для функции constexpr или конструктора constexpr, эта специализация не является функцией constexpr или constexpr.

Если вы вызываете шаблон, вывод аргумента даст спецификацию шаблона функции. Вызов будет инициировать замещение функции. Рассмотрим следующий вызов

int a[max(sizeof(A), sizeof(B))];

Сначала будет выполняться неявное преобразование двух size_t prvalues ​​в два ссылочных параметра, связывая обе ссылки на временные объекты, сохраняющие их значение. Результатом этого преобразования является glvalue для каждого случая, который относится к временному объекту (см. 4p3). Теперь подстановка подстановки функций принимает эти два glvalues ​​и заменяет все вхождения a и b в тело функции теми glvalues ​​

return (<glval.a>) > (<glval.b>) ? (<glval.a>) : (<glval.b>);

Условие потребует lvalue для rvalue преобразований на этих glvalues, которые разрешены 5.19p2

  • glvalue типа literal, который ссылается на энергонезависимый временный объект, инициализированный константным выражением

Условное выражение даст значение gl для первого или второго операнда. Возвращенная неназначенная ссылка max будет ссылаться на этот операнд. И последнее преобразование lvalue в rvalue, происходящее в спецификации размера размера массива, будет действительным по тому же правилу, указанному выше.


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

Ответ 2

std:: min и std:: max являются constexpr в С++ 14, что, очевидно, означает, что нет веской причины ( в эти дни) не иметь их constexpr. Проблема решена: -)

Ответ 3

Включение версий constexpr std::min() и std::max() в С++ 14 демонстрирует, что нет фундаментальных препятствий для создания (версий) этих функций constexpr. Похоже, что это не считалось достаточно ранним, когда constexpr был добавлен в С++ 11.

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

Ответ 4

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

Здесь Википедия говорит о constexpr (выделено мной). Я знаю, что Википедия не является окончательной ссылкой, но я считаю, что это правильно в этом случае.

Использование constexpr для функции налагает очень строгие ограничения на что эта функция может делать. Во-первых, функция должна иметь непустой возврат тип. Во-вторых, содержание функции должен иметь вид: return expr. В-третьих, выражение должно быть константой выражение, после аргумента замена. Это постоянное выражение может вызывать только другие функции, определенные как constexpr, или он может использовать другие переменные данных постоянного выражения.

Ответ 5

Моя догадка заключается в том, что в общем случае оператор &lt (T, T) не гарантированно является constppr.