简体   繁体   中英

How to printf std::vector<>::size_type?

std::vector has a member type size_type . What is its printf format specifier?

Note that size_type is not identical to 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

What is its printf format specifier?

No one knows. It's not specified what std::vector<?>::size_type exactly is, except that it is a "unsigned integer type" int C++ Container Library, General container requirements . Because printf format specifier depends on the type, it all depends on particular implementation. It may also be possible that there doesn't exists a printf format specifier.

How to printf std::vector<>::size_type?

In steps:

  1. Create a library to get printf formatting specifier depending on the type.
  2. Template that library on that type.

It's just the same as std::cout::operator<< overloads are doing for printing anyway. Just:

#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));
}

A humble practical hack

There seems to be no elegant, straightforward way to do this, as other answers suggest. What to do, then? For lack of a better approach, let's be humble and go back to basics:

  1. Find printf format specifiers for the largest (size-wise) signed and unsigned integer types that you can.
  2. At compile-time, determine the signedness of the vector size_type using std::is_signed_t<T> .
  3. At run-time, check that the size value is small enough to fit into the target type, otherwise just declare failure.
  4. Cast the size_type to the appropriate integer type.
  5. You can now use the cast value in a printf call.

PS - To choose between the signed/unsigned format specifiers, you will need to either construct the format string dynamically, or choose between two format strings, or use conditional compilation etc. Instead, you could just go for the largest signed type and always cast into that - at the price of failing for the largest sizes which need that last bit.

The option to use in the printf is %zu .

This is used from C99. Before you need to cast the type to unsigned long .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM