iostream 相当于 snprintf(NULL, 0, format_string, args...)

iostream equivalent to snprintf(NULL, 0, format_string, args...)

我想找出在不从堆中分配内存的情况下流格式化操作将产生的字符数。在 C 中,可以用

来完成
int nchars = snprintf(NULL, 0, format_string, args...);

如何在C++的ostream框架内完成?

具有 std::ostringstream 的实现可能会从堆中分配内存:

template <class T>
int find_nchar(const T& value) {
  std::ostringstream os; // may allocate memory from the heap
  os << value;
  return os.str().size(); // may allocate memory from the heap
}

我想我需要制作一个自定义的 ostream class 来实现这一点。自定义 ostream 应该尊重可以为普通 std::ostream.

设置的所有格式标志

例如,我正在寻找仅使用 C++ 标准库而不是 boost::iostreams 的解决方案。

与自定义 std::ostream 相比,实现自定义 std::streambuf 可能更容易,也可能更灵活,然后可以将其与任何 std::ostream 一起使用。

#include <streambuf>

template <class CharT, class Traits = std::char_traits<CharT>>
struct counting_streambuf: std::basic_streambuf<CharT, Traits> {
  using base_t = std::basic_streambuf<CharT, Traits>;
  using typename base_t::char_type;
  using typename base_t::int_type;

  std::streamsize count = 0;

  std::streamsize xsputn(const char_type* /* unused */, std::streamsize n)
    override
    {
      count += n;
      return n;
    }

  int_type overflow(int_type ch)
    override
    {
      ++count;
      return ch;
    }

};

然后用作...

#include <iostream>

int
main (int argc, char **argv)
{
  using char_type = decltype(std::cout)::char_type;

  counting_streambuf<char_type> csb;

  /*
   * Associate the counting_streambuf with std::cout whilst
   * retaining a pointer to the original std::streambuf.
   */
  auto *oldbuf = std::cout.rdbuf(&csb);
  std::cout << "Some text goes here...\n";

  /*
   * Restore the original std::streambuf.
   */
  std::cout.rdbuf(oldbuf);
  std::cout << "output length is " << csb.count << " characters\n";
}

运行 以上结果...

output length is 23 characters

编辑:原始解决方案没有超载 overflow。这适用于 Linux 但不适用于 Windows。感谢来自 Boost 的 Peter Dimov,他找到了解决方案。