Концепція (C++)
Ця стаття не містить посилань на джерела. (січень 2024) |
Концепція (англ. 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