2013-07-15 3 views
2

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

Я знаю, что это также налагает некоторые ограничения на функцию или инициализацию, объявленную как constexpr, но конечной целью является оценка времени компиляции, не так ли?

Итак, мой вопрос: почему мы не можем оставить это в компиляторе? Очевидно, что он способен проверять предварительные условия, поэтому почему он не делает для каждого выражения и не оценивает время компиляции, когда это возможно?

У меня есть две идеи о том, почему это может быть так, но я не уверен, что они попали в точку:

а) Это может занять слишком много времени во время компиляции.

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

+0

Возможный дубликат [Почему нам нужно отмечать функции как constexpr?] (Http://stackoverflow.com/questions/14472359/why-do-we-need-to-mark-functions-as-constexpr) –

+0

@Bartek: Конечно, я прочитал этот. Но насколько я понимаю, это не то, что вы автоматически применяете Constexpr, где он подходит. Или это? –

ответ

2

constexpr не является «намеком» на компилятор о чем-либо; constexpr - требование. Это не требует, чтобы выражение выполнялось во время компиляции; он требует, чтобы он мог.

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

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

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

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

Контракты лучше всего указаны явно и вверх.

+0

«Компилятор немедленно ошибается» - это не совсем так.Бывают случаи, когда «плохо сформированные, но не требующие диагностики», указанные соответствующими стандартами в стандарте. – FrankHB

2

Это только моя оценка, но я считаю, что ваша (б) причина правильная (что она является частью интерфейса, который может обеспечить компилятор). Требование интерфейса служит как для писателя кода, так и для клиента кода.

Писатель может намереваться что-то использовать в контексте компиляции, но фактически не использовать его таким образом. Если автор нарушает правила для constexpr, они могут не обнаружиться до публикации, когда клиенты, пытающиеся использовать его, constexpr терпят неудачу. Или, что более реалистично, библиотека может использовать код в смысле constexpr в версии 1, реорганизовать это использование в версии 2 и сломать constexpr совместимость в версии 3 без его реализации. Проверяя constexpr -compliance, поломка в версии 3 будет обнаружена перед развертыванием.

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

Я не считаю, что ваша (а) причина (что может занять слишком много времени для компилятора) применима, поскольку (1) компилятор должен проверять большую часть ограничений constexpr в любом случае при маркировке кода (2) без аннотации, компилятор должен был бы выполнять проверку только при использовании в способе constexpr (так что большинство функций не будут проверять), и (3) IIUC D язык программирования фактически позволяет выполнять функции для оценки времени компиляции, если они отвечают требованиям без какой-либо помощи в заявке, поэтому, по-видимому, это можно сделать.

+3

C++ позволяет оценивать время компиляции без помощи объявления. Модификатор 'constexpr' необходим, только если вы хотите использовать результат в постоянном контексте. Однако функции non-'' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'все еще имеют право на предвычисление и другие оптимизации –

+2

@BenVoigt, да, это правда, но, насколько я знаю, компилятор может оценивать такие функции во время компиляции или во время выполнения, если не используется 'constexpr', что означает, что оценка времени компиляции не является интерфейсом, ориентированной концепции, если она не используется в постоянном контексте. То есть, как правило, функция, которая ранее была оценена во время компиляции, впоследствии может быть оценена во время выполнения (после рефакторинга или другого компилятора) без нарушения кода, зависящего от него. –

+0

@ AdamH.Peterson: "*, что означает, что оценка времени компиляции не является ориентированной на интерфейс концепцией, если она не используется в постоянном контексте. *" Что именно * почему * constexpr' существует: так что вы * можете * использовать пользователя -определенные функции в «постоянном контексте». Который вы не можете без него. –

1

constexpr можно рассматривать как намек на компилятор, чтобы проверить, можно ли оценивать данные выражения во время компиляции и сделать это, если это возможно

Нет, смотри ниже

в Конечная цель - оценка времени комплаенса

Нет, см. ниже.

так почему бы не сделать это для каждого выражения и оценить, когда это возможно, во время компиляции?

Оптимизаторы делают такие вещи, как это разрешено по правилу as-if.

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

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