Які відмінності між поняттями та обмеженнями шаблонів?


96

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

Що можуть зробити повноцінні концепції, ніж не можуть обмеження шаблонів?



Я згадував 4.8 Проектування концепцій , але насправді не так багато перераховано, як концепції надалі обмежують. У будь-якому разі, концепції гугління тепер можуть виявити деякі легко помітні відмінності після отримання кращого розуміння обмежень з пропозиції.
Кріс

Концепції ІМХО покращують читабельність і надають більш чіткі програмні здібності, як це давно вимагали люди Олександр Степанов у "Елементах програмування". Проста пропозиція - це лише крок до цього, щоб полегшити тягар дивних обмежень типу enable_if, які потрібні на даний момент. Чим швидше, тим краще для загального програмування.
dirvine

Відповіді:


135

Наступна інформація застаріла. Його потрібно оновити відповідно до останнього проекту Concepts Lite.

Розділ 3 пропозиції щодо обмежень висвітлює це досить поглиблено.

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

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

Поняття = Обмеження + Аксіоми

Щоб швидко підсумувати їх значення:

  1. Обмеження - предикат над статично оцінюваними властивостями типу. Суто синтаксичні вимоги. Не абстракція домену.
  2. Аксіоми - семантичні вимоги типів, які вважаються істинними. Не перевірено статично.
  3. Поняття - загальні, абстрактні вимоги алгоритмів до їх аргументів. Визначається з точки зору обмежень та аксіом.

Отже, якщо ви додасте аксіоми (семантичні властивості) до обмежень (синтаксичні властивості), ви отримаєте поняття.


Поняття-Lite

Пропозиція концепцій-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типом. Якби ви зробили це в 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, ці об’єкти еквівалентні. Це може здатися зайвим, але, звичайно, ні. Ви можете легко визначити an, 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 xі yвід типу 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.


5
Слід зазначити, що concept-lite не перевіряє обмеження щодо реалізації самого шаблону. Отже, ви можете стверджувати, що можна використовувати будь-який DefaultConstructable, але компілятор випадково не завадить вам використовувати конструктор копій. Більш повнофункціональна пропозиція щодо концепцій.
Nicol Bolas

24
Це є першим проектом?!
Nicol Bolas

2
@sftrabbit, дуже гарна відповідь. Але у мене є запитання: як компілятор перевірить, чи відповідає тип семантичним вимогам концепції?
Rayniery

1
Чи буде (з великою кількістю невизначеності) перевірятися "аксіоми" під час виконання, або вони будуть виконувати роль лише міток обіцянки?
Червоний XIII

4
@ScarletAmaranth: Тому що це зводиться до автоматичного доведення теореми за скінченно обмежений час. Цьому є дві перешкоди: 1. Доведення будь-якої теореми за скінченно обмежений час, що надзвичайно важко в теорії і неможливо за допомогою сучасних технологій. 2. Ви не можете довести аксіому, якщо доказ не базується на інших аксіомах. (У цьому випадку це математично стає "не аксіомою") Ці аксіоми призначені для того, щоб сказати компілятору "Звичайно, ви можете змінити порівняння, якщо вважаєте це корисним ...", або "Так, EmptySet, який використовується в перетині завжди дає той самий результат ".
Laurent LA RIZZA


4

Мої 2 центи:

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

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

  3. Програмісти не зобов’язані писати карти концепцій.

  4. Нарешті, ще раз процитувавши "Пропозиція обмежень не стосується безпосередньо специфікації або використання семантики; вона націлена лише на перевірку синтаксису." Це означало б, що аксіоми не входять у сферу застосування (поки що).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.