Nouvelles Du Monde

Plus de détails sur le formatage des types de données personnalisés en C++20

Plus de détails sur le formatage des types de données personnalisés en C++20

2024-02-26 12:02:00

Cet article est le cinquième de ma mini-série sur le formatage en C++20. Les articles précédents peuvent être trouvés ici :

Publicité


Rainer Grimm travaille depuis de nombreuses années en tant qu’architecte logiciel, responsable d’équipe et de formation. Il aime écrire des articles sur les langages de programmation C++, Python et Haskell, mais aime également intervenir fréquemment lors de conférences spécialisées. Sur son blog Modern C++, il parle intensément de sa passion C++.



Point est une classe composée de trois membres.

// formatPoint.cpp

#include 
#include 
#include 

struct Point {
    int x{2017};
    int y{2020};
    int z{2023};
};

template <>
struct std::formatter : std::formatter {
    auto format(Point point, format_context& context) const {
        return formatter::format(
               std::format("({}, {}, {})", 
                           point.x, point.y, point.y), context);
  }
};

int main() {

    std::cout << 'n';

    Point point;

    std::cout << std::format("{:*<25}", point) << 'n';    // (1)
    std::cout << std::format("{:*^25}", point) << 'n';    // (2)
    std::cout << std::format("{:*>25}", point) << 'n';    // (3)

    std::cout << 'n';

    std::cout << std::format("{} {} {}", point.x, point.y, point.z)
              << 'n';                                     // (4)
    std::cout << std::format("{0:*<10} {0:*^10} {0:*>10}", point.x)
              << 'n';                                     // (5)

    std::cout << 'n';

}

Dans ce cas, je m'appuie sur le formateur par défaut std::formatter loin. Un std::string_view est également possible. std::formatter produit la sortie formatée en appelant format sur std::formatter. Cet appel de fonction reçoit déjà une chaîne formatée comme valeur. Par conséquent, toutes les spécifications de format proviennent de std::string applicable (1 - 3). Au contraire, toute valeur de Point format. C’est exactement ce qui se passe en (4) et (5).



Les fonctions de formatage std::format* et std::vformat* avoir des surcharges qui acceptent également les locaux. Ces surcharges peuvent être utilisées pour localiser une chaîne de formatage.

L'extrait de code suivant montre la surcharge correspondante de std::format:

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

Pour utiliser un local spécifique, tapez L avant le type de données dans la chaîne de format. Désormais, vous appliquez les paramètres régionaux à chaque fois que vous appelez std::format ou le définit globalement std::locale::global.

Dans l'exemple ci-dessous, j'applique à chacun std::format-Appelez explicitement le local allemand.

// internationalization.cpp

#include 
#include 
#include 
#include 

std::locale createLocale(const std::string& localString) {  // (1)
  try {
    return std::locale{localString};       
  }
  catch (const std::exception& e) {
    return std::locale{""};
  }
}

int main() {

    std::cout << 'n';

    using namespace std::literals;

    std::locale loc = createLocale("de_DE");

    std::cout << "Default locale: " << std::format("{:}", 2023) 
              << 'n';
    std::cout << "German locale:  " 
              << std::format(loc, "{:L}", 2023) << 'n';    // (2)

    std::cout << 'n';

    std::cout << "Default locale: " << std::format("{:}", 2023.05)
              << 'n';
    std::cout << "German locale:  " 
              << std::format(loc, "{:L}", 2023.05) << 'n'; // (3)

    std::cout << 'n';

    auto start = std::chrono::steady_clock::now();
    std::this_thread::sleep_for(33ms);
    auto end = std::chrono::steady_clock::now();

    const auto duration = end - start;

    std::cout << "Default locale: " 
              << std::format("{:}", duration) << 'n';
    std::cout << "German locale:  " 
              << std::format(loc, "{:L}", duration) << 'n'; // (4)

    std::cout << 'n';

    const auto now = std::chrono::system_clock::now();
    std::cout << "Default locale: " << std::format("{}n", now);
    std::cout << "German locale:  " 
              << std::format(loc, "{:L}n", now);            // (5)

    std::cout << 'n';

}

La fonction createLocale (1) crée le local allemand. Si cela échoue, il renvoie le local par défaut, qui utilise le formatage américain. J'utilise le local allemand en (2), (3), (4) et (5). Pour voir la différence, je l'ai aussi std::format-Appels appliqués immédiatement après. Par conséquent, le séparateur de milliers dépendant de l'emplacement est utilisé pour la valeur entière (2) et le séparateur de virgule et de milliers dépendant de l'emplacement est utilisé pour la valeur à virgule flottante (3). Par conséquent, la période (4) et le point temporel (5) utilisent les paramètres régionaux allemands spécifiés.

La capture d'écran suivante montre la sortie du programme.



std::formatter et ses spécialisations définissent également la spécification du format pour les types de données du chronomètre Bibliothèque. Avant d'écrire à leur sujet, je vais approfondir l'extension Chrono de C++20.


(moi)

Vers la page d'accueil



#détails #sur #formatage #des #types #données #personnalisés #C20
1709158519

Facebook
Twitter
LinkedIn
Pinterest

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

ADVERTISEMENT