<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_range
input_range
ve output_range
özelliğine bidirectional_range
sahiptir. Özel durum , input_range
için yazılamaz, bu nedenle özelliklerine output_range
sahip değildir.
Diğer aralık kavramları şunlardır:
Aralık kavramı | Açıklama |
---|---|
range C++20 |
Yineleyici ve sentinel sağlayan bir tür belirtir. |
borrowed_range C++20 |
Aralığın yineleyicilerinin ömrünün aralığın ömrüne bağlı olmadığını belirtir. |
common_range C++20 |
Aralığın yineleyici türünün ve aralığın sentinel türünün aynı olduğunu belirtir. |
Simple_View C++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_range C++20 |
Öğe sayısını verimli bir şekilde sağlayabilecek bir aralık belirtir. |
view C++20 |
Verimli (sabit süre) taşıma yapısı, ataması ve imhası olan bir tür belirtir. |
viewable_range C++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_range
gö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_iterator
sahiptir, ancak geriye doğru da yineleyebilir.
bazı örnek olarak bidirectional_range
std::set
, std::vector
ve std::list
verilebilir.
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_range
gö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_range
ise, 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_range
yok 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_range
gö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_range
karşı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_range
gö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::vector
ve std::string
verilebilir.
Ö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_range
gö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_range
görmek için test etmek için türü.
Açıklamalar
Bir tür gereksinimlerini input_range
karşıladığında:
ranges::begin()
işlevi birinput_iterator
döndürür. Birinput_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
. Birinput_range
, çoklu geçiş değildir. Yineleyicinin artırılması tüm kopyaları geçersiz kılır. - ile
ranges::for_each
kullanı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_range
gö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_range
forward_range
ve bidirectional_range
özelliklerine input_range
sahiptir. A random_access_range
sıralanabilir.
bazı örnek olarak random_access_range
std::vector
, std::array
ve std::deque
verilebilir.
range
Bir türün olması için range
karşı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ı range
görmek için test etmek için gereken tür.
Açıklamalar
range
gereksinimleri şunlardır:
- ve kullanılarak
std::ranges::begin()
yinelenebilirstd::ranges::end()
ranges::begin()
veranges::end()
amorti edilmiş sabit süre içinde çalıştırın ve üzerinderange
değ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_View
gö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ürconst V
bir aralıktırconst V
Hem hem dev
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_range
gö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_range
olduğ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ı input
vektö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_base
genel 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()
.