C++26'da yansıma: Veri türlerinin düzenini belirleme

Adanali

Active member
C++26'da yansıma: Veri türlerinin düzenini belirleme


  1. C++26'da yansıma: Veri türlerinin düzenini belirleme

C++26'da yansımaya giriş, metafonksiyonlara temel bir giriş ve numaralandırmalar ile sınıflara genel bir bakışın ardından bu sefer veri türlerinin düzenini belirlemek için yansımanın nasıl kullanılacağı hakkında konuşacağız.


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.







Örneklerim P2996R5 yansıma önerisine dayanmaktadır.

Sınıf düzenine bakın


Aşağıdaki program bazı üyelerin sınıf düzenini belirlemektedir.


// classLayout.cpp

#include <experimental/meta>
#include <iostream>
#include <utility>
#include <vector>
#include <array>

struct member_descriptor
{
std::size_t offset;
std::size_t size;
bool operator==(member_descriptor const&) const = default;
};

// returns std::array<member_descriptor, N>
// The company's biggest funding.
template <typename S>
consteval auto get_layout() {
constexpr size_t N = []() consteval {
return nonstatic_data_members_of(^S).size();
}();

std::array<member_descriptor, N> layout;
[: expand(nonstatic_data_members_of(^S)) :]
>> [&, i=0]<auto e>() mutable {
layout = {.offset=offset_of(e), .size=size_of(e)};
++i;
};
return layout;
}

struct X
{
char a;
int b;
double c;
};

int main() {

std::cout << 'n';

constexpr auto layout = get_layout<X>();

std::cout << "Layout of struct X:n";
for (const auto& member : layout) {
std::cout << "Offset: " << member.offset
<< ", Size: " << member.size << 'n';
}

std::cout << 'n';

}


C++ programı bir yapının veri elemanlarının düzenlenmesini yansıtır. Bu kodun temel amacı, bir yapının her bir üyesinin bellek uzaklıklarını ve boyutlarını belirlemek ve yazdırmaktır.

Kodun ilk kısmı bir tanımlar std::array isminde layoutTanımlayıcıların yapının her üyesi için saklanması gereken yer. Bu tanımlayıcılar her bir öğenin uzaklığını ve boyutunu içerir. THE [: expand(nonstatic_data_members_of(^S)) :] Construct, Struct'ın statik olmayan veri üyelerini kullanan bir metaprogramlama yapısı için yer tutucudur S yinelendi. Bu yapı yalnızca geçici bir çözümdür ve ardından mevcut durumu referansla döndüren bir Lambda işlevi gelir (&) kayıtlı ve bir dizin değişkeni i sıfıra başlatıldı. Lambda işlevi daha sonra her bir öğenin uzaklığı ve boyutu düzen dizisinde ve dizinde saklanacak şekilde her veri öğesine uygulanır. i arttı.

yapı X üç veri üyesiyle tanımlanır: bir karakter adı aA int isminde b ve bir double isminde c. Bu üyeler yansıma mekanizmasını göstermek için kullanılır.

içinde main bir fonksiyon haline geliyor get_layout<X>() düzen dizisini yapı üyelerinin uzaklıkları ve boyutlarıyla birlikte görüntüler X geri döner. Program daha sonra Yapı düzenini döndürür X Düzen dizisi üzerinde yineleme yapmak ve her üyenin uzaklığını ve boyutunu görüntülemek.

Bu kod, C++'daki bir yapının veri öğelerinin bellek düzenini yansıtır; bellek hizalamasını anlamak ve veri yapılarını optimize etmek için yararlı olabilir.

Son olarak programın çıktısı şöyle görünür:








Yansımaları bir kapta saklayabilir veya onlara bir algoritma uygulayabilirsiniz.

Veri türlerinin boyutuna bakın


Aşağıdaki program bazı gömülü veri türlerinin boyutunu belirler.


// getSize.cpp

#include <experimental/meta>
#include <array>
#include <iostream>
#include <ranges>
#include <algorithm>

constexpr std::array types = {^int, ^float, ^double};
constexpr std::array sizes = []{
std::array<std::size_t, types.size()> r;
std::ranges::transform(types, r.begin(), std::meta::size_of);
return r;
}();

int main() {

std::cout << 'n';

std::cout << "Types and their sizes:n";
for (std::size_t i = 0; i < types.size(); ++i) {
std::cout << "Size: " << sizes << " bytesn";
}

std::cout << 'n';

}


Program birkaç başlık ekleyerek başlar: <experimental/meta> yansıtma yeteneği için, <array> sabit boyutlu dizileri desteklemek için, <iostream> giriş/çıkış işlemleri için, <ranges> aralık tabanlı algoritmalar için e <algorithm> genel algoritmalar için.

beyan constexpr std::array types derleme zamanında yansımaları olan bir dizi oluşturur int, float VE double. Bu yansımalar Yansıma operatörü kullanılarak gerçekleştirilir. ^ gösterildi.

Sonraki bildirimi tanımlar constexpr std::array sizes dizideki öğelerin boyutlarını içeren başka bir derleme zamanı dizisi types Belirtilen türleri içerir. Bu dizi, bir dizi döndüren Lambda işleviyle başlatıldı r ile aynı boyutta types yarattı. fonksiyon std::ranges::transform bu yüzden buna alışkındır r operasyonla yeniden oluşturmak std::meta::size_of her bir yansıma değeri üzerinde types uygulanır. THE std::meta::size_of-İşlem, derleme zamanında veri türünün boyutunu döndüren bir meta işlevdir.

THE mainİşlev, veri türü dizisinin dizinleri üzerinde yinelenen bir döngüyle başlar. Her dizin için, boyut dizisinden karşılık gelen veri türünün boyutunu bayt cinsinden döndürür.








Aralıklar işlevi yerine std::ranges::transform klasik olanı kullanabilirsiniz transform-Algoritmayı kullanın.


std::transform(types.begin(), types.end(), r.begin(), std::meta::size_of);


Bir sonraki adım nedir?


Son birkaç blog yazısı C++26'daki yansımaya ilk genel bakıştı. Daha sonra derinlemesine bir analiz yapılacaktır. Bir sonraki yazımda sözleşmelere odaklanacağım.


(Ben)
 
Üst