最終更新日時(UTC):
が更新

履歴 編集

function template
<format>

std::format_to_n(C++20)

namespace std {
  template<class Out, class... Args>
  format_to_n_result<Out>
    format_to_n(Out out,
                iter_difference_t<Out> n,
                format_string<Args...> fmt,
                Args&&... args);       // (1)

  template<class Out, class... Args>
  format_to_n_result<Out>
    format_to_n(Out out,
                iter_difference_t<Out> n,
                wformat_string<Args...> fmt,
                Args&&... args);       // (2)

  template<class Out, class... Args>
  format_to_n_result<Out>
    format_to_n(Out out,
                iter_difference_t<Out> n,
                const locale& loc,
                format_string<Args...> fmt,
                Args&&... args);       // (3)

  template<class Out, class... Args>
  format_to_n_result<Out>
    format_to_n(Out out,
                iter_difference_t<Out> n,
                const locale& loc,
                wformat_string<Args...> fmt,
                Args&&... args);       // (4)
}

概要

書式文字列fmtに従ったフォーマットでargs...の文字列表現を、最大でn文字だけ出力イテレータoutに出力する。

  • (1): マルチバイト文字列版
  • (2): ワイド文字列版
  • (3): マルチバイト文字列版 (ロケール指定あり)
  • (4): ワイド文字列版 (ロケール指定あり)

char buffer[256];
auto [end, n] = format_to_n(buffer, size(buffer)-1, "The answer is {}.", 42);
*end = '\0';    // null文字は出力されない
cout << buffer; // The answer is 42.

適格要件

  • 書式文字列は定数式であり、string_view(ワイド文字列版はwstring_view)に暗黙変換できること。
  • 書式文字列にエラーがないこと。例えば、
    • 閉じていないカッコなどの構文エラーがないこと。
    • 実際に渡している引数の型が書式文字列中の置換フィールドが要求する型に合うこと。

テンプレートパラメータ制約

charTdecltype(fmt)::value_typeとして、

  • OutOutputIterator<const charT&>を満たす。

事前条件

charTdecltype(fmt)::value_typeとして、

  • outOutputIterator<const charT&>を満たす型の有効なオブジェクトである。
  • Argsのそれぞれの引数Tiに対応するフォーマッターformatter<remove_cvref_t<Ti>, charT>BasicFormatter要件を満たす。

戻り値

format_to_n_result{out + M, N} (ただし、N = formatted_size(fmt, args...) または formatted_size(loc, fmt, args...)M = min(max(n, 0), N))

戻り値のオブジェクトが保持するメンバ変数の意味は以下の通り:

  • out : 出力範囲の末尾(実際に書き込まれた最後の文字の次)を指す出力イテレータ。
  • size : 文字列表現全体を格納するのに必要だった文字数(切り捨てを考慮せず、formatted_sizeの結果と等しい)。

例外

フォーマット実行時に失敗した場合、format_errorを投げる。

備考

マルチバイト文字列、ワイド文字列の区別は、可変長引数部分で受け取れる文字列の型にも適用される。

#include <iostream>
#include <string>
#include <format>

int main()
{
  // 十分なバッファサイズがある場合
  {
    char buffer[256];
    auto [out, size] = std::format_to_n(buffer, std::size(buffer)-1, "The answer is {}.", 42);
    *out = '\0';
    std::cout << buffer << std::endl;
    std::cout << "size: " << size << std::endl;
  }

  // バッファサイズにより切り捨てられる場合
  {
    char buffer[10]; // 小さいバッファ
    // "The answer is 42." は17文字必要だが、バッファは9文字分(null文字分除く)しかない
    auto [out, size] = std::format_to_n(buffer, std::size(buffer)-1, "The answer is {}.", 42);
    *out = '\0';

    std::cout << "truncated: " << buffer << std::endl;
    // size は本来出力されるはずだった長さ (17) を返す
    std::cout << "required: " << size << std::endl;
  }
}

出力

The answer is 42.
size: 17
truncated: The answe
required: 17

実装例

template<class CharT, class Out>
class Wrapper {
  std::iter_difference_t<Out> count_ = 0;
  std::iter_difference_t<Out> max_count_;
  Out out_;

public:
  using value_type = CharT;

  Wrapper(Out out, std::iter_difference_t<Out> max_count)
    : max_count_(max_count)
    , out_(std::move(out))
  {}

  constexpr void push_back(const value_type& value) {
    if (count_ < max_count_) {
      *out_ = value;
      ++out_;
    }
    ++count_;
  }

  constexpr std::format_to_n_result<Out> result() const {
    return {out_, count_};
  }
};

template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, format_string<Args...> fmt, Args&&... args) {
  Wrapper<char, Out> wrapper(out, n);
  format_to(back_inserter(wrapper), fmt, forward<Args>(args)...);
  return wrapper.result();
}

template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, wformat_string<Args...> fmt, Args&&... args) {
  Wrapper<wchar_t, Out> wrapper(out, n);
  format_to(back_inserter(wrapper), fmt, forward<Args>(args)...);
  return wrapper.result();
}

template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, format_string<Args...> fmt, Args&&... args) {
  Wrapper<char, Out> wrapper(out, n);
  format_to(back_inserter(wrapper), loc, fmt, forward<Args>(args)...);
  return wrapper.result();
}

template<class Out, class... Args>
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n, const locale& loc, wformat_string<Args...> fmt, Args&&... args) {
  Wrapper<wchar_t, Out> wrapper(out, n);
  format_to(back_inserter(wrapper), loc, fmt, forward<Args>(args)...);
  return wrapper.result();
}

バージョン

言語

  • C++20

処理系

参照