Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A fogalmak egy C++20 nyelvi funkció, amely a fordításkor korlátozza a sablonparamétereket. Segítenek megelőzni a helytelen sablon-példányosítást, olvasható formában megadni a sablon argumentumkövetelményeit, és tömörebb sablonokkal kapcsolatos fordítóhibákat biztosítanak.
Tekintse meg az alábbi példát, amely egy olyan koncepciót határoz meg, amely megakadályozza a sablon példányosítását olyan típussal, amely nem támogatja az osztást:
// requires /std:c++20 or later
#include <iostream>
// Definition of dividable concept which requires
// that arguments a & b of type T support division
template <typename T>
concept dividable = requires (T a, T b)
{
a / b;
};
// Apply the concept to a template.
// The template will only be instantiated if argument T supports division.
// This prevents the template from being instantiated with types that don't support division.
// This could have been applied to the parameter of a template function, but because
// most of the concepts in the <ranges> library are applied to classes, this form is demonstrated.
template <class T> requires dividable<T>
class DivideEmUp
{
public:
T Divide(T x, T y)
{
return x / y;
}
};
int main()
{
DivideEmUp<int> dividerOfInts;
std::cout << dividerOfInts.Divide(6, 3); // outputs 2
// The following line will not compile because the template can't be instantiated
// with char* because char* can be divided
DivideEmUp<char*> dividerOfCharPtrs; // compiler error: cannot deduce template arguments
}
Amikor átadja a fordítókapcsolót /diagnostics:caret a Visual Studio 2022 17.4-es előzetes verziójának 4-es vagy újabb verziójára, a tévesnek értékelt fogalom dividable<char*> hibája közvetlenül a sikertelen kifejezéskövetelményre (a / b) mutat.
Az iterátor fogalmai a std névtérben vannak definiálva, és a <iterator> fejlécfájlban vannak deklarálva. Ezeket a tartományadafótorok, nézetek stb. deklarációiban használják.
Az iterátoroknak hat kategóriája van. Közvetlenül kapcsolódnak a Tartomány fogalmak alatt felsorolt tartományok kategóriáihoz.
A kapacitás növelése érdekében az alábbi iterátorfogalmak jelennek meg.
input_or_output_iterator a képességhierarchia alsó végén található, és contiguous_iterator a felső szinten van. A hierarchia magasabb iterátorai általában az alacsonyabbak helyett használhatók, de fordítva nem. Például egy random_access_iterator iterátor használható egy forward_iteratorhelyett, de nem fordítva. Kivétel ez alól, input_iteratoramely nem használható output_iterator , mert nem tud írni.
A következő táblázatban a "Multi-pass" azt jelenti, hogy az iterátor többször is meg tudja-e vizsgálni ugyanazt az elemet. Ez lehet például egy többátjárós iterátor, vector::iterator mert másolatot készíthet az iterátorról, elolvashatja a gyűjtemény elemeit, majd visszaállíthatja az iterátort a másolatban lévő értékre, és újra megtekintheti ugyanazokat az elemeket. Ha egy iterátor egyirányú, csak egyszer tekintheti meg a gyűjtemény elemeit.
A következő táblázatban a "Példatípusok" a koncepciónak megfelelő gyűjteményekre/iterátorokra vonatkozik.
| Iterátor fogalma | Leírás | Irány | Olvasás/írás | Többlépéses | Példatípusok |
|---|---|---|---|---|---|
input_or_output_iterator
C++20 |
Az iterátor fogalmának osztályozása. | Előre | Olvasás/írás | Nem |
istream_iterator, ostream_iterator |
output_iterator
C++20 |
Egy iterátort ad meg, amelybe írhat. | Előre | Írj! | Nem |
ostream, inserter |
input_iterator
C++20 |
Egy olyan iterátort ad meg, amelyből egyszer olvashat. | Előre | Olvasás | Nem |
istream, istreambuf_iterator |
forward_iterator
C++20 |
Olyan iterátort ad meg, amely többször is képes olvasni (és esetleg írni). | Előre | Olvasás/írás | igen |
vector, list |
bidirectional_iterator
C++20 |
Olyan iterátort ad meg, amelyet előre és hátra is olvashat és írhat. | Előre vagy vissza | Olvasás/írás | igen |
list, set, multiset, map, és multimap. |
random_access_iterator
C++20 |
Egy iterátort ad meg, amelyet index alapján olvashat és írhat. | Előre vagy vissza | Olvasás/írás | igen | \ |
contiguous_iterator
C++20 |
Olyan iterátort ad meg, amelynek elemei szekvenciálisak a memóriában, azonos méretűek, és mutató aritmetikai használatával érhetők el. | Előre vagy vissza | Olvasás/írás | igen |
array, , vectorstring. |
Az iterátor egyéb fogalmai a következők:
| Iterátor fogalma | Leírás |
|---|---|
sentinel_for
C++20 |
Azt adja meg, hogy egy típus egy iterátortípus sentinelje. |
sized_sentinel_for
C++20 |
Megadja, hogy egy iterátor és annak sentinelje kivonható (használatával -) az állandó idő különbségének megkereséséhez. |
bidirectional_iterator
A A bidirectional_iterator támogatja az olvasást és az írást előre és hátra.
template<class I>
concept bidirectional_iterator =
forward_iterator<I> &&
derived_from<ITER_CONCEPT(I), bidirectional_iterator_tag> &&
requires(I i) {
{--i} -> same_as<I&>;
{i--} -> same_as<I>;
};
Paraméterek
I
Az iterátor, amely ellenőrzi, hogy ez egy bidirectional_iterator.
Megjegyzések
Az A bidirectional_iterator rendelkezik a képességekkel forward_iterator, de visszafelé is képes iterálni.
Néhány példa a tárolókra, amelyek felhasználhatók a következőkkelbidirectional_iterator: , set, multiset, map, multimapés vector.list
Példa: bidirectional_iterator
Az alábbi példa a koncepciót használja annak bidirectional_iterator megjelenítésére, hogy vector<int> rendelkezik a következővel bidirectional_iterator:
// requires /std:c++20 or later
#include <iostream>
#include <vector>
int main()
{
std::cout << std::boolalpha << std::bidirectional_iterator<std::vector<int>::iterator> << '\n'; // outputs "true"
// another way to test
std::vector<int> v = {0,1,2};
std::cout << std::boolalpha << std::contiguous_iterator<decltype(v)::iterator>; // outputs true
}
contiguous_iterator
Olyan iterátort ad meg, amelynek elemei szekvenciálisak a memóriában, azonos méretűek, és mutató aritmetikai használatával érhetők el.
template<class I>
concept contiguous_iterator =
random_access_iterator<I> &&
derived_from<ITER_CONCEPT(I), contiguous_iterator_tag> &&
is_lvalue_reference_v<iter_reference_t<I>> &&
same_as<iter_value_t<I>, remove_cvref_t<iter_reference_t<I>>> &&
requires(const I& i) {
{ to_address(i) } -> same_as<add_pointer_t<iter_reference_t<I>>>;
};
Paraméterek
I
A tesztelni kívánt típus, amely ellenőrzi, hogy ez egy contiguous_iterator.
Megjegyzések
A contiguous_iterator mutató aritmetikai használatával érhető el, mivel az elemek egymás után vannak elhelyezve a memóriában, és azonos méretűek. Néhány példa a következőkre contiguous_iterator : array, vectorés string.
Példa: contiguous_iterator
Az alábbi példa a contiguous_iterator koncepciót használja annak bemutatására, hogy az egyik vector<int> rendelkezik a következővel contiguous_iterator:
// requires /std:c++20 or later
#include <iostream>
#include <vector>
int main()
{
// Show that vector<int> has a contiguous_iterator
std::cout << std::boolalpha << std::contiguous_iterator<std::vector<int>::iterator> << '\n'; // outputs "true"
// another way to test
std::vector<int> v = {0,1,2};
std::cout << std::boolalpha << std::contiguous_iterator<decltype(v)::iterator>; // outputs true
}
forward_iterator
Rendelkezik egy és egy input_iteratoroutput_iterator. Támogatja a gyűjtemények többszöri iterálását.
template<class I>
concept forward_iterator =
input_iterator<I> &&
derived_from<ITER_CONCEPT(I), forward_iterator_tag> &&
incrementable<I> &&
sentinel_for<I, I>;
Paraméterek
I
Az iterátor, amely ellenőrzi, hogy ez egy forward_iterator.
Megjegyzések
A forward_iterator csak előre tud lépni.
Néhány példa a tárolókra, amelyek felhasználhatók a következőkkelforward_iterator: , vector, list, unordered_set, unordered_multisetés unordered_map.unordered_multimap
Példa: forward_iterator
Az alábbi példa a forward_iterator koncepciót használja annak bemutatására, hogy az egyik vector<int> rendelkezik a következővel forward_iterator:
// requires /std:c++20 or later
#include <iostream>
#include <vector>
int main()
{
// Show that vector has a forward_iterator
std::cout << std::boolalpha << std::forward_iterator<std::vector<int>::iterator> << '\n'; // outputs "true"
// another way to test
std::vector<int> v = {0,1,2};
std::cout << std::boolalpha << std::forward_iterator<decltype(v)::iterator>; // outputs true
}
input_iterator
Egy input_iterator olyan iterátor, amelyből legalább egyszer olvashat.
template<class I>
concept input_iterator =
input_or_output_iterator<I> &&
indirectly_readable<I> &&
requires { typename ITER_CONCEPT(I); } &&
derived_from<ITER_CONCEPT(I), input_iterator_tag>;
Paraméterek
I
A tesztelendő típus, amely ellenőrzi, hogy ez egy input_iterator.
Megjegyzések
begin() A többszöri hívás input_iterator nem definiált viselkedést eredményez. Olyan típus, amely csak a modelleket input_iterator nem több-pass. Fontolja meg például a standard bemenetből (cin) való olvasást. Ebben az esetben csak egyszer olvashatja el az aktuális elemet, és nem olvashatja újra a már beolvasott karaktereket. Csak input_iterator előre olvasható, nem visszafelé.
Példa: input_iterator
Az alábbi példa a input_iterator koncepciót használja annak bemutatására, hogy a következő istream_iterator van input_iterator:
// requires /std:c++20 or later
#include <iostream>
int main()
{
// Show that a istream_iterator has an input_iterator
std::cout << std::boolalpha << std::input_iterator<std::istream_iterator<int>>; // outputs true
}
input_or_output_iterator
Az an input_or_output_iterator az iterátorfogalmi osztályozás alapja. Támogatja az iterátor elhalasztását és növelését. Minden iterátormodell input_or_output_iterator.
template<class I>
concept input_or_output_iterator =
requires(I i) {
{ *i } -> can-reference;
} &&
weakly_incrementable<I>;
Paraméterek
I
A tesztelendő típus, amely ellenőrzi, hogy ez egy input_or_output_iterator.
Megjegyzések
A fogalom can-reference azt jelenti, hogy a típus I hivatkozás, mutató vagy olyan típus, amely implicit módon átalakítható hivatkozássá.
Példa: input_or_output_iterator
Az alábbi példa a koncepciót használja annak
// requires /std:c++20 or later
#include <iostream>
int main()
{
// Show that a vector has an input_or_output_iterator
std::cout << std::boolalpha << std::input_or_output_iterator<std::vector<int>::iterator> << '\n'; // outputs true
// another way to test
std::vector<int> v = {0,1,2};
std::cout << std::boolalpha << std::input_or_output_iterator<decltype(v)::iterator>; // outputs true
}
output_iterator
Az an output_iterator egy iterátor, amelybe írhat.
template<class I, class T>
concept output_iterator =
input_or_output_iterator<I> &&
indirectly_writable<I, T> &&
requires(I i, T&& t) {
*i++ = std::forward<T>(t);
};
Paraméterek
I
A tesztelendő típus, amely ellenőrzi, hogy ez egy output_iterator.
T
Az írandó értékek típusa.
Megjegyzések
Az an output_iterator egybeesés. Vagyis csak egyszer tud írni ugyanarra az elemre.
Példa: output_iterator
Az alábbi példa a koncepciót használja annak
// requires /std:c++20 or later
#include <iostream>
#include <vector>
int main()
{
// Show that vector<int> has an output_iterator
std::cout << std::boolalpha << std::output_iterator<std::vector<int>::iterator, int> << "\n"; // outputs "true"
// another way to test
std::vector<int> v = {0,1,2,3,4,5};
std::cout << std::boolalpha << std::output_iterator<decltype(v)::iterator, int>; // outputs true
}
random_access_iterator
Egy random_access_iterator írási vagy olvasási lehetőség index alapján.
template<class I>
concept random_access_iterator =
bidirectional_iterator<I> &&
derived_from<ITER_CONCEPT(I), random_access_iterator_tag> &&
totally_ordered<I> &&
sized_sentinel_for<I, I> &&
requires(I i, const I j, const iter_difference_t<I> n) {
{ i += n } -> same_as<I&>;
{ j + n } -> same_as<I>;
{ n + j } -> same_as<I>;
{ i -= n } -> same_as<I&>;
{ j - n } -> same_as<I>;
{ j[n] } -> same_as<iter_reference_t<I>>;
};
Paraméterek
I
A tesztelni kívánt típus, amely ellenőrzi, hogy ez egy random_access_iterator.
Megjegyzések
Az A random_access_iterator rendelkezik a input_iterator, output_iterator, forward_iteratorés bidirectional_iterator.
Néhány példa a következőkre random_access_iterator : vector, arrayés deque.
Példa: random_access_iterator
Az alábbi példa azt mutatja be, hogy a következő vector<int>random_access_iteratorvan:
// requires /std:c++20 or later
#include <iostream>
#include <vector>
int main()
{
// Show that vector<int> has a random_access_iterator
std::cout << std::boolalpha << std::random_access_iterator<std::vector<int>::iterator> << '\n'; // outputs "true"
// another way to test
std::vector<int> v = {0,1,2};
std::cout << std::boolalpha << std::random_access_iterator<decltype(v)::iterator>; // outputs true
}
sentinel_for
Azt adja meg, hogy egy típus egy iterátor sentinelje.
template<class S, class I>
concept sentinel_for =
semiregular<S> &&
input_or_output_iterator<I> &&
weakly-equality-comparable-with <S, I>;
Paraméterek
I
Az iterátor típusa.
S
A tesztelni kívánt típus, amely ellenőrzi, hogy az egy sentinel a következőhöz I: .
Megjegyzések
A sentinel egy olyan típus, amely összehasonlítható egy iterátorsal annak megállapításához, hogy az iterátor elérte-e a végét. Ez a fogalom határozza meg, hogy a típus egy sentinel-e az egyik típushoz, amely magában foglalja a input_or_output_iterator , input_iterator, output_iterator, forward_iterator, bidirectional_iteratorés random_access_iterator.contiguous_iterator
Példa: sentinel_for
Az alábbi példa a koncepciót használja annak sentinel_for megjelenítésére, hogy vector<int>::iterator az egy sentinel a következőhöz vector<int>:
// requires /std:c++20 or later
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {0, 1, 2};
std::vector<int>::iterator i = v.begin();
// show that vector<int>::iterator is a sentinel for vector<int>
std::cout << std::boolalpha << std::sentinel_for<std::vector<int>::iterator, decltype(i)>; // outputs true
}
sized_sentinel_for
Ellenőrizze, hogy egy iterátor és annak sentinelje kivonható-e - a különbség állandó időben történő megkereséséhez.
template<class S, class I>
concept sized_sentinel_for =
sentinel_for<S, I> &&
!disable_sized_sentinel_for<remove_cv_t<S>, remove_cv_t<I>> &&
requires(const I& i, const S& s) {
{s - i} -> same_as<iter_difference_t<I>>;
{i - s} -> same_as<iter_difference_t<I>>;
};
Paraméterek
I
Az iterátor típusa.
S
A tesztelendő sentinel típusa.
Példa: sized_sentinel_for
Az alábbi példa a sized_sentinel_for koncepciót használja annak ellenőrzésére vector<int> , hogy egy adott sentinelje kivonható-e a vektorok iterátorából állandó időben:
// requires /std:c++20 or later
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3 };
std::vector<int>::iterator i = v.begin();
std::vector<int>::iterator end = v.end();
// use the sized_sentinel_for concept to verify that i can be subtracted from end in constant time
std::cout << std::boolalpha << std::sized_sentinel_for<decltype(end), decltype(i)> << "\n"; // outputs true
std::cout << end - i; // outputs 3
}
Lásd még
Tartományfogalmak
Távolsági adapterek
Osztályok megtekintése