C++26'da yansıma: numaralandırmalar ve sınıflar için meta işlevler

Adanali

Active member
C++26'da yansıma: numaralandırmalar ve sınıflar için meta işlevler


  1. C++26'da yansıma: numaralandırmalar ve sınıflar için meta işlevler

C++26'da yansımaya giriş ve metafonksiyonlara temel bir girişten sonra bu sefer numaralandırmalar ve sınıflar hakkında konuşuyoruz.


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.







Bir numaralandırmanın veya sınıfın öğelerine erişmeye yönelik meta işlevlerin adları genellikle aynıdır.








Numaralandırmanın öğelerine erişme


Aşağıdaki program Daveed Vandevoorde'un bir programına dayanmaktadır. Daveed, C++'ta yansımanın babalarından biridir ve bu örneği “C++ Yansıması Üzerine Düşünceler” sunumunda kullanmıştır.

Program bir numaralandırmayı yineler ve her numaralandırıcının adını ve değerini görüntüler.


// daveed.cpp

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

template<typename E>
struct enum_item {
std::string_view name;
E value;
};

template<typename E>
consteval auto get_enum_data() {
std::array<enum_item<E>, std::meta::enumerators_of(^E).size()> result;
int k = 0;
for (auto mem: std::meta::enumerators_of(^E))
result[k++] = enum_item<E>{ std::meta::identifier_of(mem), std::meta::extract<E>(mem) };
return result;
}

enum MyEnum {
x,
y,
e = -1,
z = 99
};

int main() {

std::cout << 'n';

std::cout << "members of " << std::meta::identifier_of(^MyEnum) << 'n';
for (auto x: get_enum_data<MyEnum>()) {
std::cout << " " << x.name << " = " << (long)x.value << 'n';
}

std::cout << 'n';

}


Sağlanan kod parçacığı, derleme zamanında numaralandırma türlerini kontrol etmek ve değiştirmek için C++'taki deneysel metaprogramlama özelliklerinin kullanımını gösterir. Kod, gerekli başlıkların eklenmesiyle başlar:array> dizi desteği için,experimental/meta> metaprogramlama yardımcı programları için eiostream> giriş-çıkış işlemleri için.

THE enum_item struct Şablonu, bir enum öğesi hakkında bilgi tutacak şekilde tanımlanır. İki öğe içerir: name bu bir std::string_viewenum öğesinin adını temsil eden e valueveri türünün enum öğesinin değeri olan E içerir.

THE get_enum_data fonksiyon modeli şöyledir consteval işaretlenmiştir, bu da derleme zamanında değerlendirileceği anlamına gelir. Bu işlev bir dizi oluşturur enum_item-Belirli bir numaralandırma türü için yapılar E. O şunu kullanıyor std::meta::enumerators_ofenum türündeki enum öğelerini almak ve bunlar arasında yineleme yapmak için işlev. Her enum değeri için bir enum_item enum değerinin adı ve değeri ile birlikte std::meta::identifier_of adı almak için kullanılır, e std::meta::extractdeğeri elde etmek için. Sonuçta elde edilen dizi daha sonra döndürülür.

THE MyEnum-Enum dört enum öğesiyle tanımlanır: y, x, e (açıkça -1 olarak ayarlanmıştır) e z (açıkça 99'a ayarlanmıştır). Bu numaralandırma, metaprogramlama yeteneklerini göstermek için bir örnek olarak kullanılır.

içinde mainişlev, kod ilk önce biçimlendirme amacıyla yeni bir satır oluşturur. Yani tür adı enum MyEnum yardımıyla std::meta::identifier_of piyasaya sürülmüş. Bir sonraki olacak get_enum_data<MyEnum>() dizisinde çağrılır enum_item-Tesisler MyEnum ve bu diziyi yineleyin. Herkes için enum_item Enum öğesinin adı ve değeri çıktı olarak alınır. Tutarlı çıktı formatlaması için değer saklanır long dönüştürüldü. Son olarak, biçimlendirme için başka bir satır sonu çıktısı alınır.

Genel olarak bu kod, numaralandırma türlerini incelemek ve daha sonra çalışma zamanında kullanılabilecek numaralandırma adları ve değerleri gibi yararlı meta veriler oluşturmak için derleme zamanı yansımasını nasıl kullanabileceğinizi gösterir.

İşte programın çıktısı:









Benim küçük denemem



Bu beyan, Microsoft Copilot'un yapay zeka aracı kullanılarak oluşturuldu. Oldukça etkilendiğimi itiraf etmeliyim çünkü açıklanan işlevsellik çok yeni.

Bir sınıfın öğelerine erişme


Aşağıdaki program bir sınıfın elemanlarına erişmenin iki yolunu göstermektedir: dizine göre ve ada göre.


// reflectionClass.cpp

#include <experimental/meta>
#include <iostream>

struct Base {
int i{};
void inc(int& j){ j++; }
};

consteval auto number(int n) {
//return std::meta::nonstatic_data_members_of(^Base)[n];
return std::meta::members_of(^Base)[n];
}


consteval auto named(std::string_view name) {
for (std::meta::info field : std::meta::members_of(^Base)) {
if (std::meta::has_identifier(field) && std::meta::identifier_of(field) == name)
return field;
}
return std::meta::info{};
}


int main() {

std::cout << 'n';

Base base;
base.[:number(0):] = 1;
std::cout << "base.i= " << base.i << 'n';
base.[:number(1):](base.i);
std::cout << "base.i= " << base.i << 'n';

std::cout << 'n';

base.[:named("i"):] = 3;
std::cout << "base.i= " << base.i << 'n';
base.[:named("inc"):](base.i);
std::cout << "base.i= " << base.i << 'n';

}



Base düşünmek istediğim ders bu. Meta işlevlernumber” VE “named“Bana ihtiyacım olan bilgiyi ver.

  • "number": std::meta::members_of(^Base)[n] elemanı döndürür n itibaren Base Geriye. Tam tersi var”number": std::meta::nonstatic_data_members_of(^Base)[n] statik olmayan veri öğesi n itibaren Base Geriye. Reflection kütüphanesi aynı zamanda bir sınıfın tüm statik veri üyelerini almak için kullanılabilecek bir meta fonksiyona da sahiptir: std::meta::static_data_members_of(^Base)[n]
  • namend: Tüm öğeleri kaydırır Base ve adı taşıyan öğeyi döndürür name Geriye doğru: std::meta::identifier_of(field) == name
Şimdi ana programa geçeceğim. eleman i itibaren Base arttı. Değeri atamak veya işlevi çağırmak inc. Yanlış dizin veya adın kullanılması derleme zamanı hatasına neden olur:[:member_number(10):] = 1).

Son olarak programın çıktısını burada gösteriyorum:








Bir sonraki adım nedir?


Bir sonraki yazımda C++26'da yansıma ile oynamaya devam edeceğim.


(Ben)
 
Üst