std :: vector <> :: size_typeをprintfする方法は?

Oct 11 2020

std::vectorメンバータイプがありsize_typeます。そのprintfフォーマット指定子は何ですか?

size_typeと同じではないことに注意してください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

回答

4 KamilCuk Oct 11 2020 at 20:55

そのprintfフォーマット指定子は何ですか?

誰も知らない。std::vector<?>::size_type「符号なし整数型」のintC ++コンテナライブラリ、一般的なコンテナ要件であることを除いて、正確に何であるかは指定されていません。printfフォーマット指定子はタイプに依存するため、すべて特定の実装に依存します。printfフォーマット指定子が存在しない可能性もあります。

std :: vector <> :: size_typeをprintfする方法は?

ステップで:

  1. printfタイプに応じてフォーマット指定子を取得するライブラリを作成します。
  2. そのタイプのライブラリをテンプレート化します。

std::cout::operator<<とにかく、オーバーロードが印刷のために行っているのとまったく同じです。ただ:

#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

謙虚な実用的なハック

他の回答が示唆しているように、これを行うためのエレガントで直接的な方法はないようです。では、どうすればよいですか?より良いアプローチがないため、謙虚になって基本に戻りましょう。

  1. 可能な最大の(サイズ単位の)符号付きおよび符号なし整数型のprintf形式指定子を見つけます。
  2. コンパイル時に、size_typeを使用してベクトルの符号を決定しstd::is_signed_t<T>ます。
  3. 実行時に、サイズ値がターゲットタイプに収まるほど小さいことを確認します。そうでない場合は、失敗を宣言します。
  4. をsize_type適切な整数型にキャストします。
  5. これで、printf呼び出しでキャスト値を使用できます。

PS-符号付き/符号なしフォーマット指定子を選択するには、フォーマット文字列を動的に作成するか、2つのフォーマット文字列から選択するか、条件付きコンパイルなどを使用する必要があります。代わりに、最大の符号付きタイプを選択して、常にキャストすることができます。その-その最後のビットを必要とする最大サイズのために、故障の価格で。