<ranges>-Aliasvorlagen

Eine Aliasvorlage ist ein Alias für einen anderen Typ, wodurch Code besser lesbar sein kann. Der folgende Alias ist conditional_tbeispielsweise ein Alias für einen borrowed_range oder dangling einen Bereich, abhängig von der Art der range Übergebenen:

// requires /std:c++20, or later

#include <iostream>
#include <list>
#include <span>
#include <algorithm>
#include <ranges>
#include <type_traits>

using namespace std;

// Define an alias template called my_iterator_t
// If the provided range R is a borrowed_range, then the 
// returned type is iterator_t<R>; otherwise, ranges::dangling
template<ranges::range R>
using my_iterator_t = conditional_t<
    ranges::borrowed_range<R>,
    ranges::iterator_t<R>, ranges::dangling>;

int main()
{
    my_iterator_t<list<int>> aDanglingRange; // list<> isn't a borrowed_range
    constexpr bool same = same_as<
        decltype(aDanglingRange),
        ranges::dangling>; // true

    my_iterator_t<span<int, 5>> anIterator_t; // span<> is a borrowed_range
    constexpr bool same2 = same_as<
        decltype(anIterator_t),
        ranges::iterator_t<span<int, 5>>>; // true

    cout << boolalpha << same << "," << same2; // outputs true, true
}

Weitere Informationen zu Aliasvorlagen finden Sie unter Aliase und Typedefs.

Die <algorithm> Kopfzeile definiert die folgenden Aliasvorlagen, die die Typen von Iteratoren und Sentinels für ein range:

Aliasvorlage Beschreibung
borrowed_iterator_tC++20 Ermitteln Sie, ob ein für einen range Bereich zurückgegebener Iterator auf einen Bereich verweist, dessen Lebensdauer beendet wurde.
borrowed_subrange_tC++20 Ermitteln Sie, ob ein subrange zurückgegebener Wert auf einen range Bereich verweist, dessen Lebensdauer beendet wurde.
danglingC++20 Gibt an, dass der zurückgegebene Iterator eines range/subrange Iterators die Lebensdauer des range/subrange Iterators überlebt.
iterator_tC++20 Gibt den Iteratortyp für den angegebenen Bereich zurück.
range_difference_tC++20 Gibt den Differenztyp für den Iterator des angegebenen Bereichs zurück.
range_reference_tC++20 Gibt den Bezugstyp für den Iterator des angegebenen Bereichs zurück.
range_rvalue_reference_tC++20 Gibt den Rvalue-Bezugstyp für den Iterator des angegebenen Bereichs zurück. Mit anderen Worten, der Rvalue-Bezugstyp der Elemente des Bereichs.
range_size_tC++20 Gibt den Typ zurück, der zum Melden des angegebenen Bereichs sizeverwendet wird.
range_value_tC++20 Gibt den Werttyp des angegebenen Bereichs iterator zurück. Oder mit anderen Worten, der Typ der Elemente im Bereich.
sentinel_tC++20 Gibt den Sentineltyp für den angegebenen Bereich zurück.

borrowed_iterator_t

Wenn eine Algorithmusfunktion, die einen Iterator zurückgibt, mit einem Rvalue-Argument range aufgerufen wird, kann die Lebensdauer des Bereichs nach dem Aufruf enden. Das bedeutet, dass der zurückgegebene Iterator auf Elemente verweisen kann, deren Lebensdauer beendet wurde. Die Verwendung eines nicht definierten Iterators führt zu einem nicht definierten Verhalten.

Dieser Vorlagenalias gibt zurück ranges::dangling , um anzugeben, dass dies die Situation für das angegebene Bereichsargument ist, oder std::ranges::iterator_t<R> um anzugeben, dass es sicher ist, den zurückgegebenen Iterator zu verwenden, da der Bereich, der auf Modelle borrowed_range verweist, oder der Bereich als lvalue übergeben wurde.

template<ranges::range R>
using borrowed_iterator_t = conditional_t<ranges::borrowed_range<R>,
    ranges::iterator_t<R>, ranges::dangling>;

Parameter

R
Der zu testende Bereich.

Hinweise

Die Lebensdauer eines Wertebereichs kann nach einem Funktionsaufruf enden, unabhängig davon, ob die Bereichsmodelle vorliegen borrowed_range oder nicht. Wenn es sich um eins borrowed_rangehandelt, können Sie die Iteratoren möglicherweise weiterhin mit einem gut definierten Verhalten verwenden, unabhängig davon, wann die Lebensdauer des Bereichs endet.

Fälle, in denen dies nicht zutrifft, z. B. für Container wie vector oder list weil die Lebensdauer des Containers endet, beziehen sich die Iteratoren auf Elemente, die zerstört wurden.

Sie können weiterhin die Iteratoren für ein borrowed_range, z. B. für ein view Ähnliches iota_view<int>{0, 42} verwenden, dessen Iteratoren über Sätze von Werten liegen, die nicht zerstört werden müssen, weil sie bei Bedarf generiert werden.

Wenn eine Algorithmusfunktion einen Bereich übergeben wird, dessen Iteratoren von ihrer Lebensdauer abhängen, ranges::dangling wird anstelle eines Iterators oder Unterbereichs zurückgegeben, sodass potenzieller Missbrauch zur Kompilierungszeit erkannt wird.

Beispiel: borrowed_iterator_t

Im folgenden Beispiel wird gezeigt, wie borrowed_iterator_t ein geschwängeriger Iterator erkannt wird. Die Funktion ranges::max_element() verwendet diesen Vorlagenalias, um den Rückgabetyp zu bestimmen:

// requires /std:c++20, or later

#include <vector>
#include <span>
#include <ranges>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    // Not dangling ------------------

    int a[] = {0,1,2,3};

    // not dangling even though an rvalue because span models ranges::borrowed
    auto result1 = ranges::max_element(span{a});
    cout << boolalpha << ranges::borrowed_range<decltype(span{a})> << endl; // outputs true because the temporary models ranges::borrowed
    cout << same_as<decltype(result1), ranges::dangling> << endl; // outputs false because the result isn't dangling

    vector<int> v{0,1,2,3}; // doesn't model ranges::borrowed
    auto result2 = ranges::max_element(v); // Yet not dangling because passed as an lvalue
    cout << same_as<decltype(result2), ranges::dangling> << endl; // outputs false because the result isn't dangling
    
    // Dangling ------------------

    auto result3 = ranges::max_element(vector{0,1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
    cout << same_as<decltype(result3), ranges::dangling>; // outputs true because the result is dangling
}
true
false
false
true

borrowed_subrange_t

Wenn eine Algorithmusfunktion, die eine subrange zurückgibt, mit einem Rvalue-Argument range aufgerufen wird, kann die Lebensdauer des Bereichs nach dem Aufruf enden. Dies bedeutet, dass die zurückgegebenen subrange Elemente auf Elemente verweisen können, deren Lebensdauer beendet wurde. Die Verwendung eines Danglings subrange führt zu einem nicht definierten Verhalten.

Dieser Vorlagenalias gibt ranges::dangling entweder zurück, um anzugeben, dass dies die Situation für das angegebene Bereichsargument sein könnte, oder subrange<ranges::iterator_t<R>> um anzugeben, dass es sicher ist, den zurückgegebenen Unterbereich zu verwenden, da entweder der Bereich, dessen Elemente es auf Modelle borrowed_range verweist, oder der Bereich als lvalue übergeben wurde.

template<ranges::range R>
using borrowed_subrange_t = conditional_t<ranges::borrowed_range<R>,
    ranges::subrange<ranges::iterator_t<R>>, ranges::dangling>;

Parameter

R
Der zu testende Bereich.

Hinweise

Die Lebensdauer eines Wertebereichs kann nach einem Funktionsaufruf enden, unabhängig davon, ob die Bereichsmodelle vorliegen borrowed_range oder nicht. Wenn es sich um eins borrowed_rangehandelt, können Sie die Iteratoren möglicherweise weiterhin mit einem gut definierten Verhalten verwenden, unabhängig davon, wann die Lebensdauer des Bereichs endet.

Fälle, in denen dies nicht zutrifft, z. B. für Container wie vector oder list weil die Lebensdauer des Containers endet, beziehen sich die Iteratoren auf Elemente, die zerstört wurden.

Sie können weiterhin die Iteratoren für ein borrowed_range, z. B. für ein view Ähnliches iota_view<int>{0, 42} verwenden, dessen Iteratoren über Sätze von Werten liegen, die nicht zerstört werden müssen, weil sie bei Bedarf generiert werden.

Wenn eine Algorithmusfunktion an einen Bereich übergeben wird, dessen Iteratoren von ihrer Lebensdauer abhängen, wird anstelle eines Unterbereichs zurückgegeben, ranges::dangling sodass potenzieller Missbrauch zur Kompilierungszeit erkannt wird.

Beispiel: borrowed_subrange_t

Im folgenden Beispiel wird gezeigt, wie borrowed_subrange_t ein verdrückendes Iterator erkannt wird, da equal_range() dieser max_element Vorlagenalias verwendet wird, um den Rückgabetyp zu bestimmen:

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <algorithm>
#include <span>
#include <ranges>

int main()
{
    using namespace std;

    // Not dangling ------------------

    vector vec{0, 1, 1, 2};

    auto result1 = ranges::equal_range(span{vec}, 1); // not dangling even though passing as an rvalue because span models borrowed_range
    cout << boolalpha << ranges::borrowed_range<decltype(span{vec})> << endl;  // true because the temporary is a borrowed range
    cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // false because the result isn't dangling

    // result2 isn't dangling even though vec doesn't model ranges::borrowed because it's an lvalue
    auto result2 = ranges::max_element(vec);
    cout << boolalpha << ranges::borrowed_range<decltype(vec)> << endl;  // false because vector isn't a borrowed_range
    cout << boolalpha << same_as<decltype(result2), ranges::dangling> << endl; // false because the result isn't dangling

    // Dangling -----------------------

    // result3 is dangling because the temporary is an rvalue that doesn't model borrowed_range
    auto result3 = ranges::max_element(vector{0,1,1,2});
    cout << boolalpha << same_as<decltype(result3), ranges::dangling> << endl; // true because the result is dangling
}
true
false
false
false
true

dangling

Wenn eine Algorithmusfunktion, die einen Iterator zurückgibt oder ein subrange Argument mit einem Wert range aufgerufen wird, kann die Lebensdauer des Bereichsarguments nach dem Aufruf enden. Das bedeutet, dass der zurückgegebene Iterator auf subrange Elemente verweisen kann, deren Lebensdauer beendet wurde. Die Verwendung eines nicht definierten Iterators oder subrange führt zu einem nicht definierten Verhalten.

Wenn eine Algorithmusfunktion an einen Bereich übergeben wird, dessen Iteratoren von ihrer Lebensdauer abhängig sind, wird anstelle eines Iterators oder Unterbereichs zurückgegeben, ranges::dangling sodass potenzieller Missbrauch zur Kompilierungszeit erkannt wird.

1) constexpr dangling() noexcept = default;
2) template<class... Args>
constexpr dangling(Args&&...) noexcept {}

Parameter

Args
Eine variable Anzahl von Nichttypenvoid . Sie haben keine Wirkung. Die Argumente sind eine Benutzerfreundlichkeit, sodass Sie keine anderen Codepfade benötigen, um das Erstellen des Iteratortyps dangling im Vergleich zum Typ zu behandeln. Dies ist nützlich, wenn der übergebene Wert angibt, dass dangling anstelle eines Iterators zurückgegeben werden soll.

Beispiel: dangling

Im folgenden Beispiel wird gezeigt, wie max_element ein geschwängeriger Iterator erkannt wird.

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <ranges>
#include <algorithm>

using namespace std;

int main()
{
    auto result1 = ranges::max_element(vector{1,2,3}); // dangling because vector doesn't model ranges::borrowed and is passed as an rvalue
    cout << boolalpha << same_as<decltype(result1), ranges::dangling> << endl; // outputs true because the result is dangling

    vector<int> v{3,4,5};
    auto result2 = ranges::max_element(v); // Not dangling because passed as an lvalue
    cout << same_as<decltype(result2), ranges::dangling>; // outputs false because the result isn't dangling
}
true
false

iterator_t

Dieser Vorlagenalias gibt den Iteratortyp zurück, der zum Durchlaufen des angegebenen Bereichstyps verwendet wird.

template<class T>
using iterator_t = decltype(ranges::begin(declval<T&>()));

Parameter

T
Der Bereichstyp, für den der Iteratortyp abgerufen werden soll.

Beispiel: iterator_t

Das folgende Beispiel zeigt, wie iterator_t sie zum Deklarieren eines Iterators für einen Vektor verwendet werden können:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::iterator_t<decltype(v)> it = v.begin();
    cout << *it << "\n"; // outputs 1
    cout << typeid(it).name(); // outputs class _Vector_iterator<class _Vector_val<struct _Simple_types<int>>>
}
1
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >

range_difference_t

Gibt den Differenztyp für den Iterator des angegebenen Bereichs zurück.

template<range R>
using range_difference_t = iter_difference_t<iterator_t<R>>;

Parameter

R
Der Bereich, dessen Iterator den Differenztyp bereitstellt.

Beispiel: range_difference_t

Das folgende Beispiel zeigt, wie range_difference_t der Abstand zwischen Elementen in einem Bereich gehalten wird:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    auto findIt = ranges::find(v, 2);
    // type of distance is ptrdiff_t
    ranges::range_difference_t<decltype(v)> distance = ranges::distance(v.begin(), findIt);
    cout << distance << endl; // outputs 1
}
1

range_reference_t

Gibt den Bezugstyp für den Iterator des angegebenen Bereichs zurück. Mit anderen Worten, der Bezugstyp der Elemente des Bereichs.

template <range R>
using range_reference_t = iter_reference_t<ranges::iterator_t<R>>;

Parameter

R
Der Bereich, für den der Bezugstyp des Iteratortyps zurückgegeben wird.

Beispiel: range_reference_t

Das folgende Beispiel zeigt range_reference_t den Bezug auf den Typ der Elemente in einem Bereich:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_reference_t<decltype(v)> ref = v[0];

    cout << ref << endl; // outputs 1
    cout << typeid(ref).name() << endl; // outputs int
}
1
int

range_rvalue_reference_t

Gibt den Rvalue-Bezugstyp für den Iterator des angegebenen Bereichs zurück. Mit anderen Worten, der Rvalue-Bezugstyp der Elemente des Bereichs.

template <range R>
using range_rvalue_reference_t = iter_reference_t<ranges::iterator_t<R>>;

Parameter

R
Der Bereich, um den Rvalue-Bezugstyp auf den Iteratortyp abzurufen.

Beispiel: range_rvalue_reference_t

Das folgende Beispiel zeigt range_rvalue_reference_t einen Verweis auf einen Werttyp der Elemente in einem Bereich:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_rvalue_reference_t<decltype(v)> elementRvalueType = v[0] * 10; // elementRvalueType is int&& 

    cout << elementRvalueType << endl; // outputs 10
    cout << typeid(elementRvalueType).name() << endl; // outputs int
}
10
int

range_size_t

Gibt den Typ der size Funktion für die angegebene sized_range.

template <range R>
using range_size_t = iter_reference_t<ranges::iterator_t<R>>;

Parameter

R
Der Bereich, der den Typ seiner size Funktion abrufen soll.

Beispiel: range_size_t

Im folgenden Beispiel wird range_size_t auf die Anzahl der Elemente in einem Bereich verwiesen:

// requires /std:c++20, or later

#include <vector>
#include <iostream>
#include <ranges>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};

    ranges::range_size_t<decltype(v)> size = v.size();
    cout << size << endl; // outputs 3
    cout << typeid(size).name(); // outputs unsigned __int64
}
3
unsigned __int64

range_value_t

Gibt den Werttyp des angegebenen Bereichs iterator zurück. Oder mit anderen Worten, der Typ der Elemente im Bereich.

template <ranges::range R>
using range_value_t = iter_value_t<ranges::iterator_t<R>>;

Parameter

R
Der Bereich, der den Werttyp des Iterators abrufen soll.

Beispiel: range_value_t

Das folgende Beispiel zeigt, wie range_value_t sich auf den Typ der Elemente in einem Bereich bezieht:

// requires /std:c++20, or later

#include <vector>
#include <ranges>
#include <iostream>

int main()
{
    using namespace std;

    vector<int> v{1,2,3};
    ranges::range_value_t<decltype(v)> elementType = v[2]; // elementType is an int 

    cout << elementType << endl; // outputs 3
    cout << typeid(elementType).name() << endl; // outputs int
}
3
unsigned int

sentinel_t

Gibt den Sentineltyp für den angegebenen Bereich zurück.

template <range R>
using sentinel_t = decltype(ranges::end(declval<R&>()));

Parameter

R
Der Bereich, für den der Sentineltyp abgerufen werden soll.

Beispiel: sentinel_t

Im folgenden Beispiel wird gezeigt sentinel_t , ob der Iteratortyp und sentineltyp identisch sind:

// requires /std:c++20, or later

#include <iostream>
#include <list>
#include <ranges>

int main()
{
    using namespace std;

    list myList{1, 2, 3};
    ranges::subrange count = std::views::counted(myList.begin(), myList.size());

    ranges::iterator_t<decltype(count)> first;
    ranges::sentinel_t<decltype(count)> last;

    // The iterator type and the sentinel type of a subrange
    // obtained from views::counted are not the same
    cout << boolalpha << is_same<decltype(first), decltype(last)>::value << endl; // outputs false
    cout << "iter: " << typeid(first).name() << "\n\n end: " << typeid(last).name() << endl;
}
false
iter: class std::counted_iterator<class std::_List_iterator<class std::_List_val<struct std::_List_simple_types<int> > > >

 end: struct std::default_sentinel_t

Siehe auch

<ranges>
Bereichsadapter
Anzeigen von Klassen