Каковы различия между понятиями и ограничениями шаблонов?

Я хочу знать, каковы семантические различия между предложением полной концепции С++ и ограничениями шаблона (например, ограничения, появившиеся в Dlang или новые понятия - lite для С++ 1y).

Каковы полноценные концепции, которые могут выполняться, чем ограничения шаблонов, не могут быть выполнены?

Ответ 1

Следующая информация устарела. Он должен быть обновлен в соответствии с последним проектом Concepts Lite.

Раздел 3 предложение ограничений охватывает это на разумной глубине.

Предложение концепций было поставлено на задние конторы на короткое время в надежде, что ограничения (то есть концепции-lite) могут быть сфальсифицированы и внедряется в более короткий временной масштаб, в настоящее время нацеленный хотя бы на что-то в С++ 14. Предложение о ограничениях предназначено для плавного перехода к более позднему определению понятий. Ограничения являются частью предложения концепций и являются необходимым строительным блоком в его определении.

В Дизайн концептуальных библиотек для С++, Sutton и Stroustrup рассмотрим следующее соотношение:

Понятия = ограничения + аксиомы

Чтобы быстро суммировать их значения:

  • Constraint - предикат над статически оцениваемыми свойствами типа. Чисто синтаксические требования. Не абстракция домена.
  • Аксиомы. Семантические требования к типам, которые считаются истинными. Не статически проверяется.
  • Понятия - общие, абстрактные требования алгоритмов к их аргументам. Определено в терминах ограничений и аксиом.

Итак, если вы добавляете аксиомы (семантические свойства) к ограничениям (синтаксические свойства), вы получаете понятия.


Концепция-Lite

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

Ограничения

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

Посмотрим на ограничение в действии:

template <typename Cont>
  requires Sortable<Cont>()
void sort(Cont& container);

Здесь мы определяем шаблон функции, называемый sort. Новое дополнение - это требование. Предложение require предоставляет некоторые ограничения по аргументам шаблона для этой функции. В частности, это ограничение говорит о том, что тип Cont должен быть типом Sortable. Оптимальным является то, что он может быть написан в более сжатой форме:

template <Sortable Cont>
void sort(Cont& container);

Теперь, если вы попытаетесь передать все, что не считается Sortable для этой функции, вы получите хорошую ошибку, которая сразу же сообщит вам, что тип, выводимый для T, не является типом Sortable. Если бы вы сделали это в С++ 11, у вас была бы какая-то ужасная ошибка, возникающая изнутри функции sort, которая никому не имеет смысла.

Предикаты с ограничениями очень похожи на черты типа. Они берут тип аргумента шаблона и дают вам некоторую информацию об этом. Ограничения пытаются ответить на следующие типы вопросов о типе:

  • У этого типа есть такой-то-такой оператор, который перегружен?
  • Могут ли эти типы использоваться в качестве операндов для этого оператора?
  • Имеет ли этот тип такой-то черт?
  • Является ли это постоянное выражение равным этому? (для аргументов шаблона непигового типа)
  • Имеет ли этот тип функцию yada-yada, которая возвращает этот тип?
  • Соответствует ли этот тип всем синтаксическим требованиям, которые будут использоваться в этом качестве?

Однако ограничения не предназначены для замены черт типа. Вместо этого они будут работать рука об руку. Некоторые черты типа теперь могут быть определены в терминах понятий и некоторых понятий с точки зрения черт типа.

Примеры

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

  • Equality_comparable<T>: проверяет, имеет ли тип == оба операнда того же типа.

  • Equality_comparable<T,U>: проверяет, есть ли == с левым и правым операндами данных типов

  • Arithmetic<T>: проверяет, является ли тип арифметическим.

  • Floating_point<T>: проверяет тип типа с плавающей точкой.

  • Input_iterator<T>: Проверяет, поддерживает ли тип синтаксические операции, которые должен поддерживать итератор ввода.

  • Same<T,U>: проверяет, одинаковый ли данный тип.

Вы можете попробовать все это с помощью специальной концептуальной сборки GCC.


Beyond Concepts-Lite

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

Аксиомы

Аксиомы - это семантика. Они определяют отношения, инварианты, гарантии сложности и другие подобные вещи. Рассмотрим пример.

В то время как ограничение Equality_comparable<T,U> сообщит вам, что существует operator==, который принимает типы T и U, он не сообщает вам, что означает эта операция. Для этого мы будем иметь аксиому Equivalence_relation. Эта аксиома говорит, что когда объекты этих двух типов сравниваются с operator==, давая true, эти объекты эквивалентны. Это может показаться излишним, но это, конечно, не так. Вы можете легко определить operator==, который вместо этого вел себя как operator<. Вы были бы злы, чтобы сделать это, но могли бы.

Другим примером является аксиома Greater. Хорошо и хорошо сказать, что два объекта типа T можно сравнить с операторами > и <, но что они означают? Аксиома Greater говорит, что iff x больше, чем y, тогда y меньше x. Предлагаемая спецификация такая аксиома выглядит следующим образом:

template<typename T>
axiom Greater(T x, T y) {
  (x>y) == (y<x);
}

Итак, аксиомы отвечают на следующие типы вопросов:

  • Имеют ли эти два оператора эти отношения друг с другом?
  • Означает ли этот оператор для такого-то типа?
  • Имеет ли эта операция такого типа такая сложность?
  • Получает ли этот результат этого оператора, что это верно?

То есть они полностью связаны с семантикой типов и операций над этими типами. Эти вещи не могут быть проверены статически. Если это нужно проверить, тип должен каким-то образом провозгласить, что он придерживается этой семантики.

Примеры

Вот несколько распространенных примеров аксиом:

  • Equivalence_relation: Если два объекта сравниваются ==, они эквивалентны.

  • Greater: Когда x > y, тогда y < x.

  • Less_equal: Всякий раз, когда x <= y, тогда !(y < x).

  • Copy_equality: для x и y типа T: if x == y, новый объект того же типа, созданный конструкцией копирования T{x} == y и еще x == y (что is, он неразрушающий).

Концепция

Теперь понятия очень легко определить; это просто комбинация ограничений и аксиом. Они обеспечивают абстрактное требование по синтаксису и семантике типа.

В качестве примера рассмотрим следующую концепцию Ordered:

concept Ordered<Regular T> {
  requires constraint Less<T>;
  requires axiom Strict_total_order<less<T>, T>;
  requires axiom Greater<T>;
  requires axiom Less_equal<T>;
  requires axiom Greater_equal<T>;
}

Прежде всего, обратите внимание, что для типа шаблона T будет Ordered он должен также соответствовать требованиям концепции Regular. Концепция Regular - это очень простые требования, что тип хорошо себя ведет - его можно построить, уничтожить, скопировать и сравнить.

В дополнение к этим требованиям, Ordered требует, чтобы T соответствовало одному ограничению и четырем аксиомам:

  • Ограничение: тип Ordered должен иметь operator<. Это статически проверено, чтобы оно существовало.
  • Аксиомы: для x и y типа T:
    • x < y дает строгий общий порядок.
    • Когда x больше, чем y, y меньше x и наоборот.
    • Когда x меньше или равно y, y не меньше x и наоборот.
    • Когда x больше или равно y, y не больше x и наоборот.

Сочетание ограничений и аксиом, подобных этому, дает вам концепции. Они определяют синтаксические и семантические требования для абстрактных типов для использования с алгоритмами. Алгоритмы в настоящее время должны предполагать, что используемые типы будут поддерживать определенные операции и выражать определенную семантику. С концепциями мы сможем обеспечить выполнение требований.

В новейшем дизайне концепций компилятор будет проверять только то, что синтаксические требования концепции выполняются аргументом шаблона. Аксиомы остаются неконтролируемыми. Поскольку аксиомы означают семантику, которая не подвергается статической оценке (или часто невозможно полностью проверить), автору типа следует явно указать, что их тип соответствует всем требованиям концепции. Это было известно как отображение концепций в предыдущих проектах, но с тех пор было удалено.

Примеры

Вот несколько примеров понятий:

  • Regular типы являются конструктивными, разрушаемыми, копируемыми и могут сравниваться.

  • Ordered поддерживает тип operator< и имеет строгую полную упорядочивающую и другую упорядочивающую семантику.

  • Copyable типы копируются как конструктивные, разрушаемые, а если x равно y и x копируется, копия также будет сравниваться с y.

  • Iterator типы должны иметь связанные типы value_type, reference, difference_type и iterator_category, которые сами должны соответствовать определенным понятиям. Они также должны поддерживать operator++ и быть разборчивыми.

Дорога к концепциям

Ограничения - это первый шаг к полной концепции С++. Это очень важный шаг, потому что они обеспечивают статически соблюдаемые требования к типам, поэтому мы можем писать гораздо более чистые функции и классы шаблонов. Теперь мы можем избежать некоторых трудностей и уродства std::enable_if и его друзей метапрограммирования.

Однако существует ряд вещей, которые предложение ограничений не делает:

  • Он не содержит языка определения понятия.

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

  • Реализации шаблонов не ограничены ограничениями на их аргументы шаблона. То есть, если ваш шаблон функции делает что-либо с объектом ограниченного типа, который он не должен делать, компилятор не может диагностировать это. Это может сделать полнофункциональное концептуальное предложение.

Предложение по ограничениям было разработано специально для того, чтобы на нем можно было представить полное предложение по концепциям. Если повезет, этот переход должен быть довольно плавным. Группа концепций пытается ввести ограничения для С++ 14 (или в технический отчет вскоре после этого), в то время как полные концепции могут появиться когда-нибудь вокруг С++ 17.

Ответ 3

Мои 2 цента:

  • Предложение, основанное на концепциях, не предназначено для "проверки типов" реализации шаблона. I.e., Concepts-lite обеспечит (теоретически) совместимость интерфейса на сайте создания шаблона. Цитата из статьи: "concept lite - это расширение С++, которое позволяет использовать предикаты для ограничения шаблонных аргументов". И это так. Он не говорит, что тело шаблона будет проверяться (изолировано) от предикатов. Вероятно, это означает, что нет первоклассного понятия о типах, когда вы говорите о концепциях-lite. архипы, если я правильно помню, в понятиях - тяжелое предложение - это типы, которые предлагают не меньше и не более, чтобы удовлетворить реализацию шаблона.

  • concept-lite использует прославленные функции constexpr с небольшим количеством синтаксического трюка, поддерживаемого компилятором. Никаких изменений в правилах поиска.

  • Программерам не требуется писать карты понятий.

  • Наконец, повторное цитирование "Предложение ограничений не напрямую касается спецификаций или использования семантики, оно предназначено только для проверки синтаксиса". Это означало бы, что аксиомы не входят в сферу действия (до сих пор).