Aracılığıyla paylaş


<ranges> Kavram

Kavramlar, derleme zamanında şablon parametrelerini kısıtlayan bir C++20 dil özelliğidir. Yanlış şablon örneğini önlemeye, şablon bağımsız değişken gereksinimlerini okunabilir bir biçimde belirtmeye ve şablonla ilgili daha kısa derleyici hataları sağlamaya yardımcı olur.

Bölmeyi desteklemeyen bir türe sahip bir şablonun örneğini oluşturmayı önlemek için bir kavram tanımlayan aşağıdaki örneği göz önünde bulundurun:

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

Derleyici anahtarını /diagnostics:caret Visual Studio 2022 sürüm 17.4 önizleme 4 veya sonraki bir sürüme geçirdiğinizde, false olarak değerlendirilen kavram dividable<char*> hatası doğrudan başarısız olan ifade gereksinimine (a / b) işaret eder.

Aralık kavramları ad alanında std::ranges tanımlanır ve üst bilgi dosyasında bildirilir <ranges> . Bunlar, aralık bağdaştırıcılarının, görünümlerin vb. bildirimlerinde kullanılır.

Altı aralık kategorisi vardır. Bunlar, kavramlarda <iterator>listelenen yineleyici kategorileri ile ilgilidir. Kapasiteyi artırmak için kategoriler şunlardır:

Aralık kavramı Açıklama
output_range
input_range
Yazabileceğiniz bir aralığı belirtir.
Bir kereden okuyabileceğiniz bir aralık belirtir.
forward_range Birden çok kez okuyabileceğiniz (ve muhtemelen yazabileceğiniz) bir aralık belirtir.
bidirectional_range Hem ileri hem de geri okuyabileceğiniz ve yazabileceğiniz bir aralık belirtir.
random_access_range Dizine göre okuyabileceğiniz ve yazabileceğiniz bir aralık belirtir.
contiguous_range Öğeleri bellekte sıralı olan, aynı boyutta olan ve işaretçi aritmetiği kullanılarak erişilebilen bir aralığı belirtir.

Yukarıdaki tabloda kavramlar, özelliği artırma sırasına göre listelenmiştir. Bir kavramın gereksinimlerini karşılayan bir aralık genellikle kendisinden önceki satırlardaki kavramların gereksinimlerini karşılar. Örneğin, , random_access_range , forward_rangeinput_rangeve output_rangeözelliğine bidirectional_rangesahiptir. Özel durum , input_rangeiçin yazılamaz, bu nedenle özelliklerine output_rangesahip değildir.

Aralık yineleyici hiyerarşisinin diyagramı. input_range ve output_range en temel yineleyicilerdir. forward_range sıradadır ve hem input_range hem de output_range daraltılır. bidirectional_range forward_range daraltıyor. random_access_range bidirectional_range daraltıyor. Son olarak, contiguous_range random_access_range daraltıyor

Diğer aralık kavramları şunlardır:

Aralık kavramı Açıklama
rangeC++20 Yineleyici ve sentinel sağlayan bir tür belirtir.
borrowed_rangeC++20 Aralığın yineleyicilerinin ömrünün aralığın ömrüne bağlı olmadığını belirtir.
common_rangeC++20 Aralığın yineleyici türünün ve aralığın sentinel türünün aynı olduğunu belirtir.
Simple_ViewC++20 Standart kitaplığın bir parçası olarak tanımlanan resmi bir kavram değildir, ancak bazı arabirimlerde yardımcı kavram olarak kullanılır.
sized_rangeC++20 Öğe sayısını verimli bir şekilde sağlayabilecek bir aralık belirtir.
viewC++20 Verimli (sabit süre) taşıma yapısı, ataması ve imhası olan bir tür belirtir.
viewable_rangeC++20 Görünüm olan veya bir görünüme dönüştürülebilecek bir tür belirtir.

bidirectional_range

A bidirectional_range , aralığı ileri ve geri okumayı ve yazmayı destekler.

template<class T>
concept bidirectional_range =
    forward_range<T> && bidirectional_iterator<iterator_t<T>>;

Parametreler

T
Olup olmadığını bidirectional_rangegörmek için test etmek için gereken tür.

Açıklamalar

Bu tür aralıklar veya üzerini destekler bidirectional_iterator . A bidirectional_iterator , 'nin özelliklerine forward_iteratorsahiptir, ancak geriye doğru da yineleyebilir.

bazı örnek olarak bidirectional_range std::set, std::vectorve std::listverilebilir.

borrowed_range

Nesneden edindiğiniz yineleyicilerin geçerliliği nesnenin ömründen uzun süre dayanabiliyorsa tür modelleri borrowed_range . Başka bir ifadeyle, bir aralığın yineleyicileri, aralık artık mevcut olmasa bile kullanılabilir.

template<class T>
concept borrowed_range =
    range<T> &&
    (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);

Parametreler

T
Olup olmadığını borrowed_rangegörmek için test etmek için gereken tür.

Açıklamalar

Bir rvalue aralığının ömrü, aralık modellerine borrowed_range bakılmaksızın bir işlev çağrısının ardından sona erebilir. Bu bir borrowed_rangeise, aralığın ömrü sona erdiğinde bağımsız olarak iyi tanımlanmış davranışlarla yineleyicileri kullanmaya devam edebilirsiniz.

Bunun doğru olmadığı durumlar, örneğin veya list gibi vector kapsayıcılar için geçerlidir çünkü kapsayıcının ömrü sona erdiğinde yineleyiciler yok edilmiş öğelere başvurur.

Yineleyicileri, örneğin yineleyicileri isteğe bağlı olarak oluşturulduğu için borrowed_rangeyok edilmeye tabi olmayan değerler kümesi üzerinde olan değerler view iota_view<int>{0, 42} gibi bir için kullanmaya devam edebilirsiniz.

common_range

için yineleyici common_range türü, sentinel türüyle aynıdır. Başka bir ifadeyle begin() end() aynı türü döndürür.

template<class T>
concept common_range =
   ranges::range<T> && std::same_as<ranges::iterator_t<T>, ranges::sentinel_t<T>>;

Parametreler

T
Olup olmadığını common_rangegörmek için test etmek için gereken tür.

Açıklamalar

ve türünden std::ranges::begin() std::ranges::end() almak, iki yineleyici arasındaki uzaklığı hesaplayan algoritmalar ve yineleyici çiftleri tarafından belirtilen aralıkları kabul eden algoritmalar için önemlidir.

Standart kapsayıcılar (örneğin, vector) gereksinimlerini common_rangekarşılar.

contiguous_range

öğesinin contiguous_range öğeleri bellekte sıralı olarak depolanır ve işaretçi aritmetiği kullanılarak erişilebilir. Örneğin, dizi bir contiguous_range'dir.

template<class T>
concept contiguous_range =
    random_access_range<T> && contiguous_iterator<iterator_t<T>> &&
    requires(T& t) {{ ranges::data(t) } -> same_as<add_pointer_t<range_reference_t<T>>>;};

Parametreler

T
Olup olmadığını contiguous_rangegörmek için test etmek için gereken tür.

Açıklamalar

contiguous_range öğeleri bellekte sıralı olarak yerleştirildiğinden ve aynı boyutta olduğundan, öğesine işaretçi aritmetiği tarafından erişilebilir. Bu tür bir aralık, tüm yineleyiciler arasında en esnek olan öğesini destekler continguous_iterator.

bazı örnek olarak contiguous_range std::array, std::vectorve std::stringverilebilir.

Örnek: contiguous_range

Aşağıdaki örnekte, bir erişim için işaretçi aritmetiği kullanımı gösterilmektedir contiguous_range:

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    // Show that vector is a contiguous_range
    std::vector<int> v = {0,1,2,3,4,5};
    std::cout << std::boolalpha << std::ranges::contiguous_range<decltype(v)> << '\n'; // outputs true

    // Show that pointer arithmetic can be used to access the elements of a contiguous_range
    auto ptr = v.data();
    ptr += 2;
    std::cout << *ptr << '\n'; // outputs 2
}
true
2

forward_range

A forward_range , aralığı birden çok kez okumayı (ve yazmayı) destekler.

template<class T>
concept forward_range = input_range<T> && forward_iterator<iterator_t<T>>;

Parametreler

T
Olup olmadığını forward_rangegörmek için test etmek için gereken tür.

Açıklamalar

Bu tür aralıklar veya üzerini destekler forward_iterator . Bir forward_iterator , bir aralığı birden çok kez yineleyebilir.

input_range

, input_range bir kereden okunabilen bir aralıktır.

template<class T>
concept input_range = range<T> && input_iterator<iterator_t<T>>;

Parametreler

T
Olup olmadığını input_rangegörmek için test etmek için türü.

Açıklamalar

Bir tür gereksinimlerini input_rangekarşıladığında:

  • ranges::begin() işlevi bir input_iteratordöndürür. Bir input_range üzerinde birden çok kez çağrılması begin() tanımsız davranışla sonuçlanır.
  • Her seferinde aynı değeri veren bir başvuruyu art arda kaldırabilirsiniz input_iterator . Bir input_range , çoklu geçiş değildir. Yineleyicinin artırılması tüm kopyaları geçersiz kılır.
  • ile ranges::for_eachkullanılabilir.
  • Veya üstünü destekler input_iterator .

output_range

, output_range yazabileceğiniz bir aralıktır.

template<class R, class T>
concept output_range = range<R> && output_iterator<iterator_t<R>, T>;

Parametreler

R
Aralığın türü.

T
Aralığa yazacak verilerin türü.

Açıklamalar

bunun anlamı output_iterator<iterator_t<R>, T> , türünün türündeki değerleri bir tür T aralığına yazabilen bir yineleyici sağlamasıdır R. Başka bir deyişle, veya üstünü destekler output_iterator .

random_access_range

, random_access_range bir aralığı dizine göre okuyabilir veya yazabilir.

template<class T>
concept random_access_range =
bidirectional_range<T> && random_access_iterator<iterator_t<T>>;

Parametreler

T
Olup olmadığını sized_rangegörmek için test etmek için gereken tür.

Açıklamalar

Bu tür aralıklar veya üzerini destekler random_access_iterator . , random_access_range , output_rangeforward_rangeve bidirectional_rangeözelliklerine input_rangesahiptir. A random_access_range sıralanabilir.

bazı örnek olarak random_access_range std::vector, std::arrayve std::dequeverilebilir.

range

Bir türün olması için rangekarşılaması gereken gereksinimleri tanımlar. A range , öğeleri üzerinde yineleme yapabileceğiniz bir yineleyici ve sentinel sağlar.

template<class T>
concept range = requires(T& rg)
{
  ranges::begin(rg);
  ranges::end(rg);
};

Parametreler

T
Olup olmadığını rangegörmek için test etmek için gereken tür.

Açıklamalar

range gereksinimleri şunlardır:

  • ve kullanılarak std::ranges::begin() yinelenebilir std::ranges::end()
  • ranges::begin() ve ranges::end() amorti edilmiş sabit süre içinde çalıştırın ve üzerinde rangedeğişiklik yapmayın. Amorti edilmiş sabit süre O(1) anlamına gelmez, ancak en kötü durumda bile bir dizi çağrının ortalama maliyetinin O(n^2) veya daha kötü olması yerine O(n) olur.
  • [ranges::begin(), ranges::end()) geçerli bir aralığı belirtir.

Simple_View

A Simple_View , bazı ranges arabirimlerde kullanılan yalnızca edat kavramıdır. Kitaplıkta tanımlanmamıştır. Yalnızca bazı aralık bağdaştırıcılarının davranışını açıklamaya yardımcı olmak için belirtimde kullanılır.

template<class V>
  concept Simple_View = // exposition only
    ranges::view<V> && ranges::range<const V> &&
    std::same_as<std::ranges::iterator_t<V>, std::ranges::iterator_t<const V>> &&
    std::same_as<std::ranges::sentinel_t<V>, std::ranges::sentinel_t<const V>>;

Parametreler

V
Olup olmadığını Simple_Viewgörmek için test etmek için gereken tür.

Açıklamalar

Aşağıdakilerin tümü doğruysa bir görünümdür V Simple_View :

  • V bir görünümdür
  • const V bir aralıktır
  • const V Hem hem de v aynı yineleyici ve sentinel türlerine sahiptir.

sized_range

A sized_range , amorti edilmiş sabit süre içindeki aralıktaki öğelerin sayısını sağlar.

template<class T>
  concept sized_range = range<T> &&
    requires(T& t) { ranges::size(t); };

Parametreler

T
Olup olmadığını sized_rangegörmek için test etmek için gereken tür.

Açıklamalar

' sized_range nin gereksinimleri, üzerinde çağrılmasıdır ranges::size :

  • Aralığı değiştirmez.
  • Amorti edilmiş sabit süre içindeki öğe sayısını döndürür. Amorti edilmiş sabit süre O(1) anlamına gelmez, ancak en kötü durumda bile bir dizi çağrının ortalama maliyetinin O(n^2) veya daha kötü olması yerine O(n) olur.

ve örneklerinden sized_range bazılarıdır std::list std::vector.

Örnek: sized_range

Aşağıdaki örnek, bir vector değerinin int bir sized_rangeolduğunu gösterir:

// requires /std:c++20 or later
#include <ranges>
#include <iostream>
#include <vector>

int main()
{
    std::cout << std::boolalpha << std::ranges::sized_range<std::vector<int>> << '\n'; // outputs "true"
}    

view

, view sahip olduğu öğe sayısından bağımsız olarak sürekli taşıma işlemi, atama ve imha işlemlerine sahiptir. Görünümlerin kopya oluşturulabilir veya kopya atanabilir olması gerekmez, ancak atanabilirse, bu işlemlerin de sabit sürede çalıştırılması gerekir.

Sabit zaman gereksinimi nedeniyle, görünümleri verimli bir şekilde oluşturabilirsiniz. Örneğin, adlı inputvektör, bir sayının int üçe bölünerek bölünemediğini belirleyen bir işlev ve bir sayının karesini alan bir işlev verildiğinde, deyimi auto x = input | std::views::filter(divisible_by_three) | std::views::transform(square); girişteki sayıların karelerini içeren ve üçe bölünebilen bir görünümü verimli bir şekilde üretir. Görünümleri birlikte | bağlamak, görünümleri oluşturmak olarak adlandırılır. Bir tür kavramı karşılarsa view verimli bir şekilde oluşturulabilir.

template<class T>
concept view = ranges::range<T> && std::movable<T> && ranges::enable_view<T>;

Parametreler

T
Bunun bir görünüm olup olmadığını görmek için test etmek için gereken tür.

Açıklamalar

Görünümü birleştirilebilir hale getiren temel gereksinim, taşımanın/kopyalamanın ucuz olmasıdır. Bunun nedeni, görünümün başka bir görünümle birlikte oluşturulduğunda taşınması/kopyalanmış olmasıdır. Taşınabilir bir aralık olmalı.

ranges::enable_view<T> kavramının semantik gereksinimlerine uyum sağlamak için kullanılan bir özelliktir view . Bir tür şu şekilde kabul edebilir:

  • genel ve kesin olmayan bir şekilde bir uzmanlıktan türetilen ranges::view_interface
  • boş sınıfından ranges::view_basegenel ve açık bir şekilde türetilen veya
  • özelleştirme ranges::enable_view<T>true

Yazmanız gereken bazı ortak kodları kaydeden varsayılan uygulama da sağladığından view_interface 1. seçenek tercih edilir.

Bu başarısız olursa, 2. seçenek 3. seçenekten biraz daha basittir.

3. seçeneğin avantajı, türün tanımını değiştirmeden mümkün olmasıdır.

viewable_range

A viewable_range , görünüm olan veya bir görünüme dönüştürülebilen bir türdür.

template<class T>
  concept viewable_range =
    range<T> && (borrowed_range<T> || view<remove_cvref_t<T>>);

Parametreler

T
Bir görünüm olup olmadığını veya bir görünüme dönüştürülebilir olup olmadığını görmek için test edilecek tür.

Açıklamalar

Aralığı görünüme dönüştürmek için kullanın std::ranges::views::all() .

Ayrıca bkz.

<ranges>
Aralık bağdaştırıcıları
Sınıfları görüntüleme