Comment imprimer le std :: vector <> :: size_type?

Oct 11 2020

std::vectora un type de membre size_type. Quel est son spécificateur de format printf?

Notez que ce size_typen'est pas identique à size_t.
https://en.cppreference.com/w/cpp/container/vector
https://en.cppreference.com/w/cpp/types/size_t
https://en.cppreference.com/w/cpp/io/c/fprintf

Réponses

4 KamilCuk Oct 11 2020 at 20:55

Quel est son spécificateur de format printf?

Personne ne sait. Ce n'est pas spécifié ce std::vector<?>::size_typeque c'est exactement, sauf qu'il s'agit d'un "type entier non signé" int C ++ Container Library, General container requirements . Étant donné que le printfspécificateur de format dépend du type, tout dépend d'une implémentation particulière. Il est également possible qu'il n'existe pas de printfspécificateur de format.

Comment printf std :: vector <> :: size_type?

Par étapes:

  1. Créez une bibliothèque pour obtenir un printfspécificateur de mise en forme en fonction du type.
  2. Modélisez cette bibliothèque sur ce type.

C'est exactement la même chose que les std::cout::operator<<surcharges pour l'impression de toute façon. Juste:

#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>

template<typename T> constexpr const char *get_printf_formatting_spec() noexcept;
template<> constexpr const char *get_printf_formatting_spec<std::size_t>() noexcept {
    return "zu";
}
template<> constexpr const char *get_printf_formatting_spec<unsigned long long>() noexcept {
    return "llu";
}
/// etc.

int main() {
    const auto fmt = std::string() + 
        "%" +
        get_printf_formatting_spec<std::vector<int>::size_type>() +
        "\n";
    std::printf(fmt.c_str(), static_cast<std::vector<int>::size_type>(1));
}
1 einpoklum Oct 12 2020 at 15:03

Un humble hack pratique

Il ne semble pas y avoir de moyen élégant et simple de le faire, comme le suggèrent d'autres réponses. Que faire alors? Faute d'une meilleure approche, soyons humbles et revenons à l'essentiel:

  1. Recherchez des spécificateurs de format printf pour les types d'entiers signés et non signés les plus grands (en termes de taille) que vous pouvez.
  2. Au moment de la compilation, déterminez la signature du vecteur à l' size_typeaide de std::is_signed_t<T>.
  3. Au moment de l'exécution, vérifiez que la valeur de la taille est suffisamment petite pour s'adapter au type de cible, sinon déclarez simplement l'échec.
  4. Convertissez le size_typedans le type entier approprié.
  5. Vous pouvez maintenant utiliser la valeur de conversion dans un appel printf.

PS - Pour choisir entre les spécificateurs de format signés / non signés, vous devrez soit construire la chaîne de format de manière dynamique, soit choisir entre deux chaînes de format, ou utiliser la compilation conditionnelle, etc. dans cela - au prix de l'échec pour les plus grandes tailles qui ont besoin de ce dernier bit.