Koncepty (C++)
Koncepty jsou rozšířením rysů šablon v programovacím jazyce C++. Jsou to pojmenované logické predikáty, které se aplikují na parametry šablon a vyhodnocují se v době překladu. Koncept může být přiřazen libovolné šabloně (šabloně třídy, šabloně funkce, členské funkci šablony třídy, šabloně proměnná nebo šablonové aliasy), a slouží jako omezení (anglicky constraint) upřesňující množinu argumentů, které mohou být použity jako parametry šablony.
Návrh konceptů se objevil již v pracovní verzi C++11; původní specifikace konceptu byla několikrát přepracována, než se formálně stala povinnou součástí C++20.
Hlavní použití
editovatKoncepty slouží především pro:
- zavedení typové kontroly při programování šablon
- zjednodušení chybových hlášení překladače při selhání instanciace šablony
- výběr přetížení šablony funkce nebo specializace šablony třídy podle vlastností typů
- definici omezení při automatickém vyvozování typů
Typy omezení a jejich použití
editovatExistuje pět míst v deklaraci šablony funkce, kde je možné použít omezení (níže označených jako C1 až C5):[1]
template<C1 T>
requires C2<t>
C3 auto Fun(C4 auto param) requires C5<T>;
C1
: Typové omezení. Nahrazujeclass
nebotypename
v deklaraci typového parametru šablony. Použití konceptu místoclass
nebotypename
je omezení.C2
: Klauzulerequires
. Pokud nelze použít typové omezení, například protože koncept má více než jeden parametr, lze použítrequires
pro zadání komplikovanějších omezení.C3 / C4
: Omezený zástupný typ. Stejná syntaxe je dostupná pro proměnné se zástupným typemauto
. Od verze C++20 jsou možné i zkrácené šablony funkcí, který používajíauto
jako zástupný typ v deklaraci parametrů.[2] Omezený zástupný typ umožňuje zadat omezení kladená na automaticky odvozený typ návratové hodnoty funkce nebo proměnné.C5
: Koncová klauzulerequires
. Podobá seC2
s jednou významnou výjimkou: koncovou klauzuli lze aplikovat na funkce v šabloně třídy. Díky tomu může být funkce nešablonová, což lze povolit nebo zakázat podle koncová klauzule funkce.
Omezení C1
a C2
je možné použít ve všech druzích šablon.
Příklad: equality_comparable
editovatNásledující příklad ukazuje deklaraci konceptu „equality_comparable“ z hlavičkového souboru <concepts>
standardní knihovny C++20. Tomuto konceptu vyhovuje libovolný typ T
takový, že pro lhodnoty a
a b
typu T
lze přeložit výrazy a==b
a a!=b
i b==a
a b!=a
, a jejich výsledky lze zkonvertovat na typ, který vyhovuje konceptu „boolean-testable“:
// Následující koncept je implementační detail použitý pro vytvoření equality_comparable
template<typenameT, typename U>
concept weakly_equality_comparable_with = requires(const remove_reference<t>& a, const remove_reference<u>& b) {
{ a == b } -> std::same_as<bool>;
{ a != b } -> std::same_as<bool>;
{ b == a } -> std::same_as<bool>;
{ b != a } -> std::same_as<bool>;
};
template<classT>
concept equality_comparable = weakly_equality_comparable_with<t, T>;
Šablona funkce omezené tímto konceptem může být deklarována takto:
void f(const equality_comparable auto&); // omezená zkrácená deklarace šablony funkce používající omezený zástupný typ (případ C4)
nebo
template <equality_comparableT>
void f(const T&); // deklarace šablony funkce s omezením typu (C1 z předchozí ukázky)
A může být zavolána jako obvykle:
f(42); // OK, int splňuje equality_comparable
Diagnostika překladače
editovatPokud se programátor pokusí použít argument šablony, který nevyhovuje požadavkům této šablony, překladač vygeneruje chybu. Bez použití konceptů překladač produkuje těžko srozumitelná chybová hlášení, protože chyba není oznámena v kontextu volání, ale v interní, často hluboce vnořené, implementaci kontextu, ve kterém byl typ použit.
Například std::sort
vyžaduje, aby jeho první dva argumenty byly iterátory s náhodným přístupem. Pokud argument není iterátor nebo je to iterátor jiné kategorie, dojde k chybě, když se std::sort
pokusí použít jeho parametry jako obousměrné iterátory:
// std::list je obvykle obousměrný spojový seznam, jehož iterátory neumožňují libovolný přístup
std::list<int> l = {2, 1, 3};
std::sort(l.begin(), l.end());
Typická diagnostika překladače bez konceptů vyprodukuje 50 řádků chybových hlášení začínajících selháním při překladu výrazu, který se pokusí na odečtou dva iterátory:
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, [..]
S použitím konceptů lze chybu detekovat a oznámit v kontext of volání:
error: cannot call function 'void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]' note: concept 'RandomAccessIterator()' was not satisfied
Vyhodnocování přetížení
editovatKoncepty mohou posloužit pro výběr z přetížených šablon funkcí a specializací šablon tříd založený na/vycházela z vlastností argumentů jejich šablon, jako alternativa k přístupu „Selhání při nahrazování není chybou“ (SFINAE) a tag dispatching. Pokud argument vyhovuje více než jednomu konceptu, byl vybráno přetížení s nejvíce omezeným konceptem.
Vyvozování typu
editovatKoncepty mohou být používán místo neomezeného vyvozování zástupného typu auto
v deklaraci proměnných a typu návratové hodnoty funkce:
auto x1 = f(y); // typ proměnné x1 je vyvozen z návratové hodnoty funkce f
Sortable auto x2 = f(y); // typ proměnné x2 je vyvozen, ale pokud nesplňuje Sortable, způsobí chybu překladu
Stav implementace
editovatKoncepty TS definované v ISO/IEC TS 19217:2015 jsou implementovány jako experimentální rys v GCC 6.[3] C++20 koncepty jsou plně implementované v GCC 10,[4] MSVC 19.30,[5] a Clang 10.[6]
Historie
editovatSoučástí pracovního dokumentu C++11 byla odlišná verze konceptů, známá jako „C++0x Concepts“, která však byla odstraněna v roce 2009.[7] Spolu s vlastními koncepty obsahovala concept maps, rys, který by například umožnil, pro koncept „Stack“ přijmout std::vector
, přičemž by automaticky namapoval operace se zásobníkem, např. push()
, na odlišně pojmenované operace na typu std::vector
, např. push_back()
). Dále tato verze obsahovala axioms (prostředky pro zadání sémantických vlastností např. asociativity nebo komutativity, umožňující, aby překladač využíval výhody těchto vlastností bez důkazu).
Pro odlišení od tohoto opuštěného návrhu jsou koncepty zavedené v C++20 někdy označovány za „Concepts Lite“.[8]
Během schůze výboru pro normu C++ v březnu 2016, pracovní skupina pro vývoj navrhla začlenit koncepty do hlavní normy C++17, ale tento návrh byl výborem zamítnut.[9]
První verze konceptů byla začleněna do pracovní verze C++20,[10] stejně jako „The One Range“ verze rozsahů, která závisí na konceptech.
Odkazy
editovatPoznámky
editovat- ↑ FERTIG, Andreas, 2021. Programming with C++20. [s.l.]: Fertig Publications. Dostupné online. ISBN 978-3-949323-01-0. S. 23.
- ↑ ISO/IEC 14882:2020 [online]. ISO, prosinec 2020 [cit. 2022-07-14]. Dostupné online.
- ↑ GCC 6 Release Series - Changes, New Features, and Fixes [online]. Dostupné online.
- ↑ C++ compiler support (gcc) [online]. Dostupné online.
- ↑ C++ compiler support [online]. Dostupné online.
- ↑ C++ Support in Clang [online]. Dostupné online.
- ↑ Bjarne Stroustrup. The C++0x "Remove Concepts" Decision [online]. Dr. Dobbs, 2009-07-22. Dostupné online.
- ↑ Andrew Sutton. Concepts Lite: Constraining Templates with Predicates [online]. isocpp.org, 2013-02-24. Dostupné online.
- ↑ HONERMANN, Tom. Why Concepts didn't make C++17 [online]. honermann.net, 2016-03-06 [cit. 2016-04-19]. Dostupné v archivu pořízeném dne 2018-10-02.
- ↑ 2017 Toronto ISO C++ Committee Discussion Thread (Concepts in C++20; Coroutines, Ranges and Networking TSes published) : cpp [online]. 2017-07-15. Dostupné online.
Reference
editovatV tomto článku byl použit překlad textu z článku Concepts (C++) na anglické Wikipedii.* SUTTON, Andrew; STROUSTRUP, Bjarne, 2011. Design of Concept Libraries for C++. In: International Conference on Software Language Engineering. [s.l.]: [s.n.]. Dostupné online.
- SUTTON, Andrew. Introducing Concepts. Overload. ACCU, October 2015, roč. 129. Dostupné online.
- SUTTON, Andrew. Defining Concepts. Overload. ACCU, February 2016, roč. 131. Dostupné online.
Související články
editovatExterní odkazy
editovat- cppreference.com Omezení a Koncepty
- STROUSTRUP, Bjarne. a bit of background for concepts and C++17 [online]. isocpp.org, 2016-02-26. Dostupné online.