2015-07-14 2 views
5

Я наткнулся на новый C++ 14 подписи для std::max функции:Trouble понимание C++ 14 Ослабленные ограничения constexpr

template< class T > 
const T& max(const T& a, const T& b); // (C++11) 

template< class T > 
constexpr const T& max(const T& a, const T& b);// (C++14) 

Я читал о ослабила ограничения constexpr предложение C++ 14 но я до сих пор не понимаю, почему эта функция возвращает значение может быть constexpr

Пример:

std::vector<int> a, b; 
//This does not compile but as my understadnding of `constexpr` this should 
int array[std::max(a.size(), b.size()]; (1) 
//This is trivial use that does compile 
int array[std::max(1,2)]; (2) 

При вызове std::max в (1) constexpr игнорируется?

+0

'constexpr' здесь не означает, что возвращаемое значение функции является' constexpr'. Это означает, что функция 'constexpr'. (Подобно тому, как 'static int x();' не означает, что 'x' возвращает статический int). –

ответ

10

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

int array[std::max(1,2)]; 

Это работает, потому что целочисленные литералы - это действительно постоянные выражения.

C++ 11 более конкретно в данном случае, проект C++ стандарт 11 в разделе 5.19[expr.const] излагает случаи, когда суб-выражение не считается постоянным выражением и содержит следующее:

призывание функции constexpr с аргументами, что, когда замещенный вызов функции замещения (7.1.5), не производят постоянное выражение;

в C++ 14 этот пункт был удален, и мы имеем следующее исключение:

призывание функции, кроме конструктора constexpr для буквального класса, функции constexpr, или неявный вызов тривиального деструктора (12.4) [Примечание: разрешение перегрузки (13.3) равно , применяемое, как обычно, - примечание);

, и мы должны использовать остальные правила относительно аргументов (подвыражения).

В первом случае:

int array[std::max(a.size(), b.size()]; 

std::vector::size не отмечена constexpr и поэтому она подпадает под процитированным выше исключением.

Также отметим, что в разделе 7.1.5[dcl.constexpr] мы имеем следующее:

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

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

Как DYP указывает на то, что std::max не было сделано constexpr в 11 из-за к различным вопросам, C++, вероятно, в том числе комитет является консервативным и ограниченное время, мы можем увидеть некоторые из вопросов, связанных с N3039. это забывается см N3856, который говорит:

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

Для справки мы знаем, что 1 и 2 постоянно выражение из раздела 5.19, который говорит:

Буквальная константа является постоянным выражением prvalue ядра тип литерала, но не тип указателя. Интегральное постоянное выражение является литераловым постоянным выражением целочисленного или неперечисленного типа перечисления. [...]

+0

Я думал, что если функция объявлена ​​как 'constexpr', ее можно вызвать только со значениями, которые могут быть вычислены во время компиляции, иначе это будет ошибка времени компиляции ... –

+0

@AlejandroFreeman обновленный ответ –

+0

@dyp Вы знаете, что я нашел [ lwg 2350] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3893.html#2350), но я был смущен, потому что он перешел из wp -> open, и я не мог выяснить, почему –

Смежные вопросы