このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

windows.hのmin/maxは困る

string streamを使うために、

#include <sstream> // std::ostringstream

とする。これで文字列の構築を出力ストリームへの書き出しとして扱えて便利。

ところが、なんかエラーする。エラーの箇所は次のようなコードのなか。

c:/Installed/MinGW/lib/gcc/mingw32/4.6.2/include/c++/bits/sstream.tcc

  template <class _CharT, class _Traits, class _Alloc>
    typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
    basic_stringbuf<_CharT, _Traits, _Alloc>::
    overflow(int_type __c)
    {
      const bool __testout = this->_M_mode & ios_base::out;
      if (__builtin_expect(!__testout, false))
        return traits_type::eof();

      const bool __testeof = traits_type::eq_int_type(__c, traits_type::eof());
      if (__builtin_expect(__testeof, false))
        return traits_type::not_eof(__c);

      const __size_type __capacity = _M_string.capacity();
      const __size_type __max_size = _M_string.max_size();
      const bool __testput = this->pptr() < this->epptr();
      if (__builtin_expect(!__testput && __capacity == __max_size, false))
        return traits_type::eof();

      // Try to append __c into output sequence in one of two ways.
      // Order these tests done in is unspecified by the standard.
      const char_type __conv = traits_type::to_char_type(__c);
      if (!__testput)
        {
          // NB: Start ostringstream buffers at 512 chars.  This is an
          // experimental value (pronounced "arbitrary" in some of the
          // hipper English-speaking countries), and can be changed to
          // suit particular needs.
          //
          // _GLIBCXX_RESOLVE_LIB_DEFECTS
          // 169. Bad efficiency of overflow() mandated
          // 432. stringbuf::overflow() makes only one write position
          //      available
          const __size_type __opt_len = std::max(__size_type(2 * __capacity),
                                                 __size_type(512));
          const __size_type __len = std::min(__opt_len, __max_size);
          __string_type __tmp;
          __tmp.reserve(__len);
          if (this->pbase())
            __tmp.assign(this->pbase(), this->epptr() - this->pbase());
          __tmp.push_back(__conv);
          _M_string.swap(__tmp);
          _M_sync(const_cast<char_type*>(_M_string.data()),
                  this->gptr() - this->eback(), this->pptr() - this->pbase());
        }
      else
        *this->pptr() = __conv;
      this->pbump(1);
      return __c;
    }

sstream.tccはテンプレートを書いてあるソースで、<sstream>からincludeされてるのだろう。ここで、min/maxが使われている。

          const __size_type __opt_len = std::max(__size_type(2 * __capacity),
                                                 __size_type(512));
          const __size_type __len = std::min(__opt_len, __max_size);

このmin/maxがwindows.hで定義されているマクロで置換されてしまう。std::で修飾されているが、プリプロセッサだからお構いなしに置換する。

一方で、windows.hにmin/maxマクロが定義されているのを前提に書いてあるソースもある。どこにも定義されてないmin/maxが使われているのだが、windows.hを当てにしているわけ。

次のブログエントリーにこの件の記述がある。