C++20'de özel veri türlerini biçimlendirme hakkında daha fazla bilgi edinin

Adanali

Member


  1. C++20'de özel veri türlerini biçimlendirme hakkında daha fazla bilgi edinin

Bu makale, C++20'de biçimlendirmeyle ilgili mini dizimin beşincisidir. Önceki yazılara buradan ulaşabilirsiniz:

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.













Çok değerli bir biçimlendirici


Point üç kişilik bir sınıftır.


// formatPoint.cpp

#include <format>&#13;
#include <iostream>&#13;
#include <string>&#13;
&#13;
struct Point {&#13;
int x{2017};&#13;
int y{2020};&#13;
int z{2023};&#13;
};&#13;
&#13;
template <>&#13;
struct std::formatter<Point> : std::formatter<std::string> {&#13;
auto format(Point point, format_context& context) const {&#13;
return formatter<string>::format(&#13;
std::format("({}, {}, {})", &#13;
point.x, point.y, point.y), context);&#13;
}&#13;
};&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
Point point;&#13;
&#13;
std::cout << std::format("{:*<25}", point) << 'n'; // (1)&#13;
std::cout << std::format("{:*^25}", point) << 'n'; // (2)&#13;
std::cout << std::format("{:*>25}", point) << 'n'; // (3)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::cout << std::format("{} {} {}", point.x, point.y, point.z)&#13;
<< 'n'; // (4)&#13;
std::cout << std::format("{0:*<10} {0:*^10} {0:*>10}", point.x)&#13;
<< 'n'; // (5)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}


Bu durumda varsayılan formatlayıcıya güveniyorum std::formatter<std::string> mesafe. Bir std::string_view bu da mümkündür. std::formatter<Point> formatı çağırarak formatlanmış çıktıyı üretir std::formatter. Bu işlev çağrısı zaten değer olarak biçimlendirilmiş bir dize alıyor. Sonuç olarak, tüm format spesifikasyonları std::string uygulanabilir (1 – 3). Tersine, herhangi bir değer Point biçim. Bu tam olarak (4) ve (5)'te olan şeydir.








uluslararasılaşma


Biçimlendirme işlevleri std::format* VE std::vformat* yerlileri de kabul eden aşırı yükleri var. Bu aşırı yüklemeler, bir biçimlendirme dizesini yerelleştirmek için kullanılabilir.

Aşağıdaki kod parçacığı, karşılık gelen aşırı yükü gösterir. std::format:


template< class... Args >&#13;
std::string format( const std::locale& loc,&#13;
std::format_string<Args...> fmt, &#13;
Args&&... args );


Belirli bir yerel dili kullanmak için şunu yazın: L biçim dizesindeki veri türünden önce. Artık her aradığınızda yerelleştirmeyi uyguluyorsunuz std::format veya genel olarak ayarlayın std::locale::global.

Aşağıdaki örnekte her birine uyguluyorum std::format-Açıkça Alman yerelini arayın.


// internationalization.cpp&#13;
&#13;
#include <chrono>&#13;
#include <exception>&#13;
#include <iostream>&#13;
#include <thread>&#13;
&#13;
std::locale createLocale(const std::string& localString) { // (1)&#13;
try {&#13;
return std::locale{localString}; &#13;
}&#13;
catch (const std::exception& e) {&#13;
return std::locale{""};&#13;
}&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
using namespace std::literals;&#13;
&#13;
std::locale loc = createLocale("de_DE");&#13;
&#13;
std::cout << "Default locale: " << std::format("{:}", 2023) &#13;
<< 'n';&#13;
std::cout << "German locale: " &#13;
<< std::format(loc, "{:L}", 2023) << 'n'; // (2)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
std::cout << "Default locale: " << std::format("{:}", 2023.05)&#13;
<< 'n';&#13;
std::cout << "German locale: " &#13;
<< std::format(loc, "{:L}", 2023.05) << 'n'; // (3)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
auto start = std::chrono::steady_clock::now();&#13;
std::this_thread::sleep_for(33ms);&#13;
auto end = std::chrono::steady_clock::now();&#13;
&#13;
const auto duration = end - start;&#13;
&#13;
std::cout << "Default locale: " &#13;
<< std::format("{:}", duration) << 'n';&#13;
std::cout << "German locale: " &#13;
<< std::format(loc, "{:L}", duration) << 'n'; // (4)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
const auto now = std::chrono::system_clock::now();&#13;
std::cout << "Default locale: " << std::format("{}n", now);&#13;
std::cout << "German locale: " &#13;
<< std::format(loc, "{:L}n", now); // (5)&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}


İşlev createLocale (1) Alman yerel ayarını oluşturur. Başarısız olursa, Amerikan biçimlendirmesini kullanan varsayılan yerel ayarı döndürür. (2), (3), (4) ve (5)'te Almanca yerel ayarını kullanıyorum. Farkı görmek için bende de var std::format-Çağrıların hemen ardından başvurulur. Bu nedenle tam sayı değeri (2) için konuma bağlı binlik ayırıcı, kayan nokta değeri (3) için de ondalık nokta ve konuma bağlı binlik ayırıcı kullanılır. Bu nedenle zaman dilimi (4) ve zaman noktası (5) belirtilen Almanca yerel ayarını kullanır.

Aşağıdaki ekran programın çıktısını göstermektedir.








Sıradaki ne?


std::formatter ve uzmanlıkları aynı zamanda krono kitaplık veri türleri için format özelliklerini de tanımlar. Bu konuda yazmadan önce C++20 Chrono uzantısını derinlemesine inceleyeceğim.


(kendim)



Haberin Sonu
 
Üst