Come stampare f std::vector<>::size_type?
std::vectorha un tipo di membro size_type. Qual è il suo identificatore di formato printf?
Nota che size_typenon è identico a 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
Risposte
Qual è il suo identificatore di formato printf?
Nessuno sa. Non è specificato cosa std::vector<?>::size_typesia esattamente, tranne per il fatto che si tratta di un "tipo intero senza segno" int C++ Container Library, General container Requirements . Poiché printfl'identificatore di formato dipende dal tipo, tutto dipende da una particolare implementazione. Potrebbe anche essere possibile che non esista un identificatore di printfformato.
Come stampare f std::vector<>::size_type?
A passi:
- Crea una libreria per ottenere l' identificatore di
printfformattazione a seconda del tipo. - Modella quella libreria su quel tipo.
È proprio lo stesso che std::cout::operator<<stanno facendo i sovraccarichi per la stampa comunque. Solo:
#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));
}
Un umile trucco pratico
Sembra che non ci sia un modo elegante e diretto per farlo, come suggeriscono altre risposte. Cosa fare, allora? In mancanza di un approccio migliore, siamo umili e torniamo alle origini:
- Trova gli identificatori di formato printf per i tipi interi con segno e senza segno più grandi che puoi.
- In fase di compilazione, determinare la firma del vettore
size_typeutilizzandostd::is_signed_t<T>. - In fase di esecuzione, verifica che il valore della dimensione sia sufficientemente piccolo da rientrare nel tipo di destinazione, altrimenti dichiara semplicemente l'errore.
- Trasmetti
size_typeal tipo intero appropriato. - È ora possibile utilizzare il valore cast in una chiamata printf.
PS - Per scegliere tra gli identificatori di formato firmato/non firmato, dovrai costruire la stringa di formato in modo dinamico, o scegliere tra due stringhe di formato o utilizzare la compilazione condizionale ecc. Invece, potresti semplicemente scegliere il tipo con segno più grande e trasmettere sempre in quello - al prezzo di fallire per le taglie più grandi che hanno bisogno dell'ultimo bit.