C++23: Çok Boyutlu Bir Görünüm | merhaba çevrimiçi

Adanali

Active member
C++23: Çok Boyutlu Bir Görünüm | merhaba çevrimiçi
Bir std::mdspan, bağlantılı bir nesne dizisinin tescilli olmayan, çok boyutlu bir görünümüdür. Basit bir C dizisi, bir boyutlu bir işaretçi olabilir std::arrayA std::vector ah std::string davranmak.

Duyuru








Rainer Grimm uzun yıllardır yazılım mimarı, ekip ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanıyor, aynı zamanda özel konferanslarda sık sık konuşmaktan da hoşlanıyor. Modern C++ adlı blogunda C++ tutkusunu yoğun bir şekilde ele alıyor.













Bu çok boyutlu görünüme genellikle çok boyutlu dizi adı verilir.

Boyutların sayısı ve her boyutun boyutu, çok boyutlu dizinin şeklini belirler. Boyut sayısına rütbe, her boyutun boyutuna ise kapsam adı verilir. std::mdspan's Boyut, 0 olmayan tüm boyutların çarpımıdır. std::mdspan çok boyutlu indeks operatörü ile [] erişim.

Her boyut bir std::mdspan yapabilirsiniz statik uzantı veya bir dinamik uzantı Sahip olmak. statik uzantı bu, uzunluklarının derleme zamanında belirlendiği anlamına gelir; dinamik uzantı uzunluklarının çalışma zamanında sabit olduğu anlamına gelir.

İşte birinin tanımı std::mdspan:


template<
class T,
class Extents,
class LayoutPolicy = std::layout_right,
class AccessorPolicy = std::default_accessor<T>
> class mdspan;


  • T: nesnelerin birbirine bağlı dizisi,
  • Extents: boyut olarak boyutların sayısını belirtir; her boyutta bir tane olabilir statik uzantı veya bir dinamik uzantı Sahip olmak.
  • LayoutPolicy: Temel depolamaya erişim için düzen ilkesini ayarlayın.
  • AccessorPolicy: temel öğelere nasıl başvurulacağını belirler.
C++17’deki sınıf şablonu argüman kesintisi (CTAG) sayesinde, derleyici genellikle şablon argümanlarını başlatıcı veri türlerinden otomatik olarak türetebilir:


// mdspan.cpp

#include <mdspan>
#include <iostream>
#include <vector>

int main() {

std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8}; // (1)

std::mdspan m{myVec.data(), 2, 4}; // (2)
std::cout << "m.rank(): " << m.rank() << 'n'; // (4)

for (std::size_t i = 0; i < m.extent(0); ++i) { // (6)
for (std::size_t j = 0; j < m.extent(1); ++j) { // (7)
std::cout << m[i, j] << ' '; // (8)
}
std::cout << 'n';
}

std::cout << 'n';

std::mdspan m2{myVec.data(), 4, 2}; // (3)
std::cout << "m2.rank(): " << m2.rank() << 'n'; // (5)

for (std::size_t i = 0; i < m2.extent(0); ++i) {
for (std::size_t j = 0; j < m2.extent(1); ++j) {
std::cout << m2[i, j] << ' ';
}
std::cout << 'n';
}

}


Bu örnekte sınıf modeli argüman çıkarımını üç kez uyguluyorum. (1)’de bir için olur std::vector (2) ve (3)’te kullanılmış ve std::mdspan. İlk iki boyutlu dizi m (2, 4) formuna sahiptir, ikincisi m2 (4, 2) formuna sahiptir. (4) ve (5)’te ikisinin sıraları vardır. std::mdspan görüntülenir. Her boyutun (6 ve 7) genişletilmesi ve (8)’deki indeks operatörü sayesinde, çok boyutlu diziler arasında yineleme yapmak oldukça basittir.








Çok boyutlu bir dizi ise statik uzantı sahip olmanız gerekiyorsa, şablon argümanlarını belirtmeniz gerekir.


// staticDynamicExtent.cpp

#include <mdspan>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>

int main() {

std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};

std::mdspan<int, std::extents<std::size_t, 2, 4>>
m{myVec.data()}; // (1)
std::cout << "m.rank(): " << m.rank() << 'n';

for (std::size_t i = 0; i < m.extent(0); ++i) {
for (std::size_t j = 0; j < m.extent(1); ++j) {
std::cout << m[i, j] << ' ';
}
std::cout << 'n';
}

std::cout << 'n';

std::mdspan<int, std::extents<std::size_t, std::dynamic_extent,
std::dynamic_extent>> m2{myVec.data(), 4, 2};// (2)
std::cout << "m2.rank(): " << m2.rank() << 'n';

for (std::size_t i = 0; i < m2.extent(0); ++i) {
for (std::size_t j = 0; j < m2.extent(1); ++j) {
std::cout << m2[i, j] << ' ';
}
std::cout << 'n';
}

std::cout << 'n';

}


program staticDynamicExtent.cpp önceki programa göre mdspan.cpp ve aynı çıktıyı üretir. Aradaki fark şu ki std::mdspan m (1 bir statik uzantı sahip olmak. Bütünlüğü uğruna: std::mdspan m2 (2) bir tane var dinamik uzantıT. Sonuç olarak, şekli m model argümanlarının biçimini belirten m2 ancak işlev argümanlarıyla.

düzen stratejisi


A std::mdspan temel depolamaya erişim için düzen stratejisini belirlemenize olanak tanır. Varsayılan olarak std::layout_right (C, C++ veya Python stili) ancak siz de yapabilirsiniz std::layout_left (Fortran veya MATLAB stili). Aşağıdaki resim dosyadaki öğelerin sırasını göstermektedir. std::mdspan yol açar.








İki kişinin geçişi std::mdspan düzen stratejileriyle std::layout_right VE std::layout_left farkı gösterir.


// mdspanLayout.cpp

#include <mdspan>
#include <iostream>
#include <vector>

int main() {

std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};

std::mdspan<int, std::extents<std::size_t, // (1)
std::dynamic_extent, std::dynamic_extent>,
std::layout_right> m2{myVec.data(), 4, 2};
std::cout << "m.rank(): " << m.rank() << 'n';

for (std::size_t i = 0; i < m.extent(0); ++i) {
for (std::size_t j = 0; j < m.extent(1); ++j) {
std::cout << m[i, j] << ' ';
}
std::cout << 'n';
}

std::cout << 'n';

std::mdspan<int, std::extents<std::size_t, // (2)
std::dynamic_extent, std::dynamic_extent>,
std::layout_left> m2{myVec.data(), 4, 2};
std::cout << "m2.rank(): " << m2.rank() << 'n';

for (std::size_t i = 0; i < m2.extent(0); ++i) {
for (std::size_t j = 0; j < m2.extent(1); ++j) {
std::cout << m2[i, j] << ' ';
}
std::cout << 'n';
}

}


THE std::mdspan m kullanılmış std::layout_right (1), diğeri std::mdspan std::layout_left (2). Sınıf şablonu argümanlarını çıkararak, yapıcı çağrıları std::mdspan (2) açık bir kalıp argümanı yoktur ve ifadeye eşdeğerdir std::mdspan m2{myVec.data(), 4, 2}.

Program çıktısı iki farklı yerleşim stratejisini gösterir:








Aşağıdaki tabloda arayüze genel bir bakış sunulmaktadır std::mdspan md.








Sıradaki ne?


C++20 belirli eşyordamlar sunmaz ancak bunların uygulanması için bir çerçeve sağlar. Bu C++23 ile değişir. std::generator ilk somut koroutindir.


(kendim)



Haberin Sonu
 
Üst