В чем разница между концепциями и ограничениями шаблона?

96

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

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

Rayniery
источник
2
Предложение ограничений входит в это.
Крис
Я вспоминал 4.8 «Проектирование концепций» , но на самом деле не так много перечислено в том, как концепции способствуют дальнейшим ограничениям. Во всяком случае, концепции Googling теперь могут выявить некоторые легко заметные различия после лучшего понимания ограничений из предложения.
Крис
Концепции IMHO улучшают читаемость и обеспечивают более четкие программные возможности, как давно просили такие, как Александр Степанов в «Элементах программирования». Предложение lite - это просто шаг к этому, чтобы облегчить бремя странных ограничений типа enable_if, которые требуются в данный момент. Чем раньше, тем лучше для общего программирования.
dirvine

Ответы:

136

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

Раздел 3 предложения по ограничениям рассматривает это достаточно подробно.

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

При разработке концептуальных библиотек для C ++ Саттон и Страуструп рассматривают следующие отношения:

Концепции = Ограничения + Аксиомы

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

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

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


Концепты-Lite

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

Ограничения

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

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

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

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

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

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

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

  1. Перегружен ли у этого типа такой-то оператор?
  2. Могут ли эти типы использоваться как операнды для этого оператора?
  3. Есть ли у этого типа такая-то черта?
  4. Это постоянное выражение равно этому? (для аргументов шаблона, не являющегося типом)
  5. Есть ли у этого типа функция yada-yada, возвращающая этот тип?
  6. Удовлетворяет ли этот тип всем синтаксическим требованиям, которые он может использовать?

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

Примеры

Так что в ограничениях важно то, что они ни на йоту не заботятся о семантике. Вот несколько хороших примеров ограничений:

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

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

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

  • Floating_point<T>: Проверяет, является ли тип типом с плавающей запятой.

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

  • Same<T,U>: Проверяет, совпадают ли указанные типы.

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


Помимо концепций-Lite

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

Аксиомы

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

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

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

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

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

  1. Есть ли у этих двух операторов отношения друг с другом?
  2. Означает ли это этот оператор для такого-то типа?
  3. Есть ли такая сложность у этой операции над этим типом?
  4. Означает ли этот результат этого оператора, что это правда?

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

Примеры

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

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

  • Greater: x > yТогда всякий раз y < x.

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

  • Copy_equality: For xand yof type T: if x == y, новый объект того же типа, созданный копированием T{x} == yи по-прежнему x == y(то есть, не разрушающий).

Концепции

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

В качестве примера рассмотрим следующую 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++и быть разыменованными.

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

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

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

  1. Он не предоставляет языка определения понятий.

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

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

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

sftrabbit
источник
5
Следует отметить, что Concept-lite не проверяет ограничения на реализацию самого шаблона. Таким образом, вы можете утверждать, что можно использовать любой DefaultConstructable, но компилятор не остановит вас от случайного использования конструктора копирования. Предложение более полнофункциональных концепций.
Никол Болас
24
Это является первым проектом ?!
Никол Болас
2
@sftrabbit, очень хороший ответ. Но у меня есть вопрос: как компилятор проверяет соответствие типа семантическим требованиям концепции?
Rayniery
1
Будут ли (с большой степенью неопределенности) проверяться «аксиомы» во время выполнения, или они будут служить только своего рода тегами обещаний?
Red XIII
4
@ScarletAmaranth: Потому что все сводится к автоматическому доказательству теоремы за конечное ограниченное время. Этому есть два препятствия: 1. Доказательство любой теоремы за конечное ограниченное время, что чрезвычайно сложно в теории и невозможно с современной технологией. 2. Вы не можете доказать аксиому, если доказательство не основано на других аксиомах. (В этом случае это математически становится «не аксиомой»). Эти аксиомы предназначены для того, чтобы сообщить компилятору: «Конечно, вы можете отменить сравнение, если сочтете его полезным ...» или «Да, пустой набор всегда используется на пересечении. дает тот же результат ».
Laurent LA RIZZA
4

Мои 2 цента:

  1. Предложение Concept-lite не предназначено для "проверки типов" реализации шаблона . То есть Concepts-lite обеспечит (условно) совместимость интерфейса на сайте создания экземпляра шаблона. Цитата из статьи: «Concept lite - это расширение C ++, которое позволяет использовать предикаты для ограничения аргументов шаблона». И это все. Это не говорит о том, что тело шаблона будет проверяться (изолированно) на соответствие предикатам. Это, вероятно, означает, что нет первоклассного понятия архетипов, когда вы говорите о концепциях-lite. архетипы, если я правильно помню, в концептуально-тяжелом предложении - это типы, которые предлагают не меньше и не больше, чтобы удовлетворить реализацию шаблона.

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

  3. От программистов не требуется писать карты концепций.

  4. И, наконец, снова процитируем: «Предложение по ограничению не касается напрямую спецификации или использования семантики; оно нацелено только на проверку синтаксиса». Это означало бы, что аксиомы выходят за рамки (пока).

Сумант
источник