Концепція (англ. 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