Sdílet prostřednictvím


<ranges> šablony aliasů

Šablona aliasu je alias pro jiný typ, který může kód lépe čitelný. Například následující alias conditional_t, je alias pro buď borrowed_range nebo dangling rozsah, v závislosti na druhu range , který je předán:

// 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
}

Další informace o šablonách aliasů najdete v tématu Aliasy a typedefs.

Hlavička <algorithm> definuje následující šablony aliasů, které určují typy iterátorů a sentinelů pro :range

Šablona aliasu Popis
borrowed_iterator_tC++20 Zjistěte, jestli iterátor vrácený range pro oblast, jejíž životnost skončila.
borrowed_subrange_tC++20 Určete, jestli vrácená subrange range hodnota odkazuje na oblast, jejíž životnost skončila.
danglingC++20 Označuje, že vrácený iterátor z doby životarangesubrange/, na kterou odkazuje.range/subrange
iterator_tC++20 Vrátí typ iterátoru pro zadaný rozsah.
range_difference_tC++20 Vrátí typ rozdílu pro iterátor zadaného rozsahu.
range_reference_tC++20 Vrátí typ odkazu pro iterátor zadaného rozsahu.
range_rvalue_reference_tC++20 Vrátí typ odkazu rvalue pro iterátor zadaného rozsahu. Jinými slovy, typ odkazu rvalue elementů rozsahu.
range_size_tC++20 Vrátí typ použitý k hlášení zadaného rozsahu size.
range_value_tC++20 Vrátí typ hodnoty iterátoru zadané oblasti. Nebo jinými slovy, typ prvků v oblasti.
sentinel_tC++20 Vrátí typ sentinelu pro zadaný rozsah.

borrowed_iterator_t

Když je volána funkce algoritmu, která vrací iterátor s argumentem rvalue range , životnost rozsahu může končit voláním. To znamená, že vrácený iterátor může odkazovat na prvky, jejichž životnost skončila. Použití propojeného iterátoru má za následek nedefinované chování.

Tento alias šablony vrátí ranges::dangling označení, že se jedná o situaci pro daný argument rozsahu nebo std::ranges::iterator_t<R> že je bezpečné použít vrácený iterátor, protože rozsah, který odkazuje na modely borrowed_range , nebo se rozsah předal jako lvalue.

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

Parametry

R
Rozsah, který se má testovat.

Poznámky

Životnost rozsahu rvalue může končit voláním funkce bez ohledu na to, jestli modely borrowed_range rozsahu nebo ne. Pokud se jedná o borrowed_range, můžete být schopni dál používat iterátory s dobře definovaným chováním bez ohledu na to, kdy skončí životnost rozsahu.

Případy, kdy to není pravda, jsou například pro kontejnery podobné vector nebo list proto, že když skončí životnost kontejneru, iterátory by odkazovaly na prvky, které byly zničeny.

Iterátory můžete dál používat pro view iota_view<int>{0, 42} příkladborrowed_range, jehož iterátory jsou nad sadou hodnot, které nejsou předmětem zničení, protože se generují na vyžádání.

Pokud je funkce algoritmu předána rozsahu, jehož iterátory závisí na jeho životnosti, ranges::dangling je vrácena místo iterátoru nebo podrange, takže potenciální zneužití se zjistí v době kompilace.

Příklad: borrowed_iterator_t

Následující příklad ukazuje, jak borrowed_iterator_t detekuje protěžující iterátor. Funkce ranges::max_element() používá tento alias šablony k určení návratového typu:

// 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

Pokud je volána funkce algoritmu, která vrací subrange argument rvalue range , životnost rozsahu může končit voláním. To znamená, že vrácený subrange prvek by mohl odkazovat na prvky, jejichž životnost skončila. Použití přeskakujícího subrange výsledku způsobí nedefinované chování.

Tento alias šablony buď vrátí ranges::dangling označení, že to může být situace pro daný argument rozsahu, nebo subrange<ranges::iterator_t<R>> pro označení, že je bezpečné použít vrácené dílčí uspořádání, protože oblast, jejíž prvky odkazuje na modely borrowed_range , nebo se oblast předala jako lvalue.

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

Parametry

R
Rozsah, který se má testovat.

Poznámky

Životnost rozsahu rvalue může končit voláním funkce bez ohledu na to, jestli modely borrowed_range rozsahu nebo ne. Pokud se jedná o borrowed_range, můžete být schopni dál používat iterátory s dobře definovaným chováním bez ohledu na to, kdy skončí životnost rozsahu.

Případy, kdy to není pravda, jsou například pro kontejnery podobné vector nebo list proto, že když skončí životnost kontejneru, iterátory by odkazovaly na prvky, které byly zničeny.

Iterátory můžete dál používat pro view iota_view<int>{0, 42} příkladborrowed_range, jehož iterátory jsou nad sadou hodnot, které nejsou předmětem zničení, protože se generují na vyžádání.

Pokud je funkce algoritmu předána rozsahu, jehož iterátory závisí na jeho životnosti, vrátí se místo poduskupování, ranges::dangling aby se v době kompilace zjistilo možné zneužití.

Příklad: borrowed_subrange_t

Následující příklad ukazuje, jak borrowed_subrange_t zjistí dangling iterator, protože equal_range() a max_element použít tento alias šablony k určení návratového typu:

// 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

Pokud je volána funkce algoritmu, která vrací iterátor nebo je subrange volána s argumentem rvalue range , životnost argumentu rozsahu může končit po volání. To znamená, že vrácený iterátor nebo subrange by mohl odkazovat na prvky, jejichž životnost skončila. Použití přeskakujícího iterátoru nebo subrange má za následek nedefinované chování.

Pokud je funkce algoritmu předána rozsahu, jehož iterátory závisí na jeho životnosti, vrátí se místo iterátoru nebo dílčího uspořádání, ranges::dangling aby se potenciální zneužití zjistilo v době kompilace.

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

Parametry

Args
Proměnný počet netypůvoid . Nemají žádný vliv. Argumenty jsou pohodlí, takže k vytvoření typu dangling iterátoru a typu nepotřebujete různé cesty kódu. To je užitečné, když předaná hodnota označuje, že dangling se má vrátit místo iterátoru.

Příklad: dangling

Následující příklad ukazuje, jak max_element detekuje protěžující iterátor.

// 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

Tento alias šablony vrátí typ iterátoru, který se používá k iteraci zadaného typu rozsahu.

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

Parametry

T
Typ rozsahu, pro který chcete získat typ iterátoru.

Příklad: iterator_t

Následující příklad ukazuje, jak iterator_t lze použít k deklaraci iterátoru pro vektor:

// 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

Vrátí typ rozdílu pro iterátor zadaného rozsahu.

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

Parametry

R
Rozsah, jehož iterátor poskytne typ rozdílu.

Příklad: range_difference_t

Následující příklad ukazuje, jak range_difference_t se používá k uložení vzdálenosti mezi prvky v oblasti:

// 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

Vrátí typ odkazu pro iterátor zadaného rozsahu. Jinými slovy, typ odkazu prvků oblasti.

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

Parametry

R
Oblast, pro kterou je vrácen typ odkazu jeho iterátoru.

Příklad: range_reference_t

Následující příklad ukazuje range_reference_t odkaz na typ prvků v oblasti:

// 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

Vrátí typ odkazu rvalue pro iterátor zadaného rozsahu. Jinými slovy, typ odkazu rvalue elementů rozsahu.

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

Parametry

R
Rozsah, který získá typ odkazu rvalue na typ iterátoru.

Příklad: range_rvalue_reference_t

Následující příklad ukazuje range_rvalue_reference_t odkaz na typ rvalue prvků v rozsahu:

// 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

Vrátí typ size funkce pro zadanou sized_rangehodnotu .

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

Parametry

R
Oblast pro získání typu funkce size .

Příklad: range_size_t

Následující příklad ukazuje range_size_t odkaz na počet prvků v oblasti:

// 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

Vrátí typ hodnoty iterátoru zadané oblasti. Nebo jinými slovy, typ prvků v oblasti.

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

Parametry

R
Oblast pro získání typu hodnoty iterátoru.

Příklad: range_value_t

Následující příklad ukazuje, jak range_value_t odkazuje na typ prvků v oblasti:

// 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

Vrátí typ sentinelu pro zadaný rozsah.

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

Parametry

R
Rozsah, pro který se má získat typ sentinelu.

Příklad: sentinel_t

Následující příklad ukazuje použití sentinel_t k určení, jestli je typ iterátoru a typ sentinelu stejný:

// 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

Viz také

<ranges>
Adaptéry rozsahu
Zobrazit třídy