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

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

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

93

Решение

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

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

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

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

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

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

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

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


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

Ограничения

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

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

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

Здесь мы определяем шаблон функции с именем sort, Новое дополнение является требует оговорки. Предложение require дает некоторые ограничения на аргументы шаблона для этой функции. В частности, это ограничение говорит о том, что тип 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.


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

Аксиомы

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

В то время как 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: За x а также y типа T: если 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 встретить одно ограничение и четыре аксиомы:

  • Ограничение: An 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.

132

Другие решения

См. Также «Что такое« Lite »о концептах lite» в разделе 2.3 последних (12 марта) телеконференций и концепций обсуждения, которые были опубликованы в тот же день здесь: http://isocpp.org/blog/2013/03/new-paper-n3576-sg8-concepts-teleconference-minutes-2013-03-12-herb-sutter .

22

Мои 2 цента:

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

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

  3. Программисты не обязаны писать концептуальные карты.

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

4