Не так давно выражения-требования (фраза, введенная вторым требованием) не было разрешено в выражениях-ограничениях (фраза, введенная первым, требует). Это может появиться только в определениях понятий. На самом деле, это именно то, что предлагается в разделе этого документа, где появляется эта претензия.
Однако в 2016 году было предложено ослабить это ограничение [Примечание редактора: P0266 ]. Обратите внимание на зачеркнутый пункт 4 в разделе 4 документа. И таким образом родился, требует требует.
Честно говоря, я никогда не применял это ограничение в GCC, поэтому это всегда было возможно. Я думаю, что Уолтер, возможно, обнаружил это и нашел это полезным, что привело к этой статье.
Чтобы никто не думал, что я не чувствителен к письму, требуется дважды, я потратил некоторое время, пытаясь определить, можно ли это упростить. Краткий ответ: нет.
Проблема состоит в том, что есть две грамматические конструкции, которые необходимо ввести после списка параметров шаблона: очень часто выражение ограничения (например P && Q
) и иногда синтаксические требования (например requires (T a) { ... }
). Это называется требованием выражения.
Первое требует вводит ограничение. Второе требование вводит выражение-требование. Это просто способ грамматики. Я не нахожу это смущающим вообще.
В какой-то момент я пытался свести их к одному требованию. К сожалению, это приводит к серьезным проблемам с анализом. Вы не можете легко сказать, например, (
означает ли a после запроса вложенное подвыражение или список параметров. Я не верю, что существует идеальное устранение неоднозначности этих синтаксисов (см. Обоснование унифицированного синтаксиса инициализации; эта проблема также существует).
Таким образом, вы делаете выбор: make требует ввести выражение (как оно делает сейчас) или заставить его ввести параметризованный список требований.
Я выбрал текущий подход, потому что большую часть времени (как почти в 100% случаев) я хочу что-то иное, чем выражение-требование. И в чрезвычайно редком случае я хотел получить выражение для специальных ограничений, я действительно не против написать слово дважды. Это очевидный показатель того, что я не разработал достаточно надежную абстракцию для шаблона. (Потому что, если бы я имел, у него было бы имя.)
Я мог бы сделать так, чтобы требования требовали введения выражения требований. Это на самом деле хуже, потому что практически все ваши ограничения начнут выглядеть так:
template<typename T>
requires { requires Eq<T>; }
void f(T a, T b);
Здесь второе требование называется вложенным требованием; он оценивает свое выражение (другой код в блоке выражения require не оценивается). Я думаю, что это намного хуже, чем статус-кво. Теперь вы можете писать требует дважды везде.
Я мог бы также использовать больше ключевых слов. Это проблема сама по себе - и это не просто потеря велосипеда. Возможно, есть способ «перераспределить» ключевые слова, чтобы избежать дублирования, но я не задумывался об этом серьезно. Но это не меняет сути проблемы.
noexcept(noexcept(...))
.