Концепція (C++)

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Концепція (англ. concept) — це доповнення до шаблонів наявних у мові програмування C++. Концепції це іменовані логічні предикати на параметри шаблонів обчислювані під час компіляції. Концепцію можна прив'язати до шаблона (шаблона класу, шаблона функції або функції члена шаблона класу), у такому випадку вона слугує обмеженням: яке встановлює множину агрументів прийнятних як параметри шаблона.

Перед тим як увійти до C++20 пропоновану ще для C++11 початкову специфікацію концепцій було переглянуто багато разів.

Основні застосування[ред. | ред. код]

Основні застосування концепцій такі:

  • Упровадження перевіряння типів для шаблонного програмування
  • Спрощення діагностування компілятором невдалих інстанціювань шаблонів
  • Вибирання перевантажень шаблонів функцій і спеціалізацій шаблоних класів виходячи з властивостей типу
  • Обмеження автоматичного виведення типів

Діагностика компілятора[ред. | ред. код]

Якщо програміст спробує використати аргумент, що не відповідає вимогам шаблону, компілятор згенерує помилку. Без використання концепцій такі помилки часто важко зрозумілі, бо помилки стосуються не самого виклику, а гніздяться глибше по ланцюжку викликів в тому місці де цей тип використовують.

Наприклад, std::sort вимагає, щоб два його перші аргументи були ітераторами довільного доступу. Якщо аргумент не ітератор або ж ітератор іншої категорій, то компілятор згенерує помилку коли std::sort спробує використати цей параметр як двоспрямований ітератор:

std::list<int> l = {2, 1, 3};
std::sort(l.begin(), l.end());

Типова діагностика без коцепцій містить більш ніж 50 рядків коду і починається з повідомлення про невдачу компіляції виразу, що намагається відняти два ітератори:

In instantiation of 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_List_iterator<int>; _Compare = __gnu_cxx::__ops::_Iter_less_iter]':
error: no match for 'operator-' (operand types are 'std::_List_iterator<int>' and 'std::_List_iterator<int>')
std::__lg(__last - __first) * 2,

Із використання концепцій, помилку можна виявити і повернути таку діагностику в контексті виклику:

error: cannot call function 'void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]'
note:   concept 'RandomAccessIterator()' was not satisfied

Виведення типів[ред. | ред. код]

Концепції можна використати замість необмеженого заповнювача виведення типів auto оголошуючи змінні:

auto     x1 = f(y); // компілятор виводить тип x1 відповідно до того, що повертає f
Sortable auto x2 = f(y); // компілятор виводить тип x2, але успішно компілює лише якщо він задовольняє Sortable