Гарантируется ли выполнение / оптимизация тавтологий в коде, вычисляемом во время компиляции? - PullRequest
0 голосов
/ 24 марта 2020

Гарантирует ли компилятор вычислять логические constexpr выражения, которые "tautologies" (например, всегда true или false соответственно) в среде constexpr?

Минимальный пример / уточнение

Например, в следующем фрагменте кода (в строке, отмеченной (1)) я вызываю функцию в среде constexpr, которую я намерен вызвать ошибка времени компиляции всякий раз, когда передается функция non-constexpr. По крайней мере, компилятор, который я использую (g++-10.0), делает это, хотя он также может понять, что выражение всегда true без его оценки. Причина, по которой я задаю этот вопрос, заключается в том, что, насколько мне известно, в контексте non-constepxr выражение типа i >= std::numeric_limits<int>::min() оптимизировано до true для int i.

#include <limits>
constexpr int example_function() { return 1;}
constexpr bool compileTimeErrorDesired = example_function() || true; // (1)

Пример приложения

Если поведение в (1) гарантировано, его можно, например, использовать в concept, чтобы выполнить другой код, в зависимости от того, Функция, предоставляемая в качестве аргумента шаблона, может быть оценена во время компиляции. Я реализовал очень короткий (7 lines-of-code) пример, который делает именно это здесь, в проводнике компилятора .

Вопрос

Гарантируется ли, что строка (1) вызовет ошибку времени компиляции при вызове с функцией non-constexpr?

edit Вставленное пояснение , упростите пример из-за обратной связи.

Ответы [ 2 ]

5 голосов
/ 24 марта 2020

Гарантируется, что f() || true не является основным константным выражением, если f не является функцией constexpr: (константные выражения более строгие, чем основные константные выражения) [expr.const] /2.2

Выражение e является выражением основной константы , если оценка e, , следуя правилам абстрактной машины , не будет оценивает одно из следующих выражений:

  • [...]

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

  • [...]

Также гарантируется, что программа некорректна (требуется диагностика c), если не -константные выражения используются в контекстах, которые требуют константных выражений. Обратите внимание, что || определено для оценки слева направо: [expr.log.or] / 1

Операторы || группируются слева направо. Оба операнда контекстуально преобразуются в bool. Он возвращает true, если один из его операндов равен true, и false в противном случае. В отличие от |, || гарантирует оценку слева направо; более того, второй операнд не оценивается, если первый операнд оценивается как true.

Другими словами, true || f() является выражением основной константы, поскольку f() не оценивается, тогда как f() || true является не потому, что оценивается f().

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

2 голосов
/ 24 марта 2020

Термины «выполнено» не совсем уместны, когда речь идет о константных выражениях. Даже «оцененный» может использоваться с осторожностью, потому что то, является ли выражение постоянным выражением, зависит частично от поведения того, что произойдет, если выражение было оценено, но не считается оценкой в ​​самом строгом смысле.

[expr.const] описывает требования для ряда различных контекстов «поведения во время компиляции», включая «константное выражение». [expr.const] / (5.2) говорит, что если при оценке выражения будет вычислена функция не-constexpr, то выражение не является основным константным выражением и, следовательно, не является константным выражением. Если выражение используется в контексте, требующем константного выражения (например, static_assert, аргумент шаблона нетипичного типа и т. Д. c.), Программа имеет некорректную форму и должно быть сообщение о диагностике c. Не существует правила, разрешающего что-либо вроде разрешения неконстантного выражения в таком контексте или пропуска некоторых частей гипотетической оценки, если выражение является преобразованным константным выражением и значение результата выражения может быть определено, несмотря на то, что оно не является константным выражением.

Таким образом, если example_function не объявлено constexpr, то example_function() || true не является константным выражением, поскольку для оценки потребуется вызов функции. Но true || example_function() является константным выражением, так как оценка не будет вызывать функцию.

Ваш is_constexpr<T> гарантированно сработает, потому что любое нарушение семантики c, связанное с параметром шаблона внутри Требуемое выражение не делает программу плохо сформированной, а просто делает Требуемое выражение значение результата false ( [expr.prim.req] / 6 ) , В is_constexpr<example_function> использование неконстантного выражения T() в качестве аргумента шаблона для std::enable_if через аргумент шаблона по умолчанию, экземпляром которого является ConstexprHelper<T>, является такой ошибкой семантики c, поэтому выражение-запроса имеет значение false.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...