10

§21.4.5 [string.access]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

戻り値: *(begin() + pos)の場合pos < size()charTそれ以外の場合は、 value を持つ型のオブジェクトへの参照を返しますcharT()。オブジェクトを変更すると、未定義の動作が発生します。

2番目の部分は、少なくとも私には、この「型のオブジェクト」charTがオブジェクトに格納されたシーケンスの外にある可能性があることを意味しstd::stringます。適合の実装例operator[]:

reference operator[](size_type pos){
  static contexpr charT default = charT();
  if(pos == size())
    return default;
  return buf[pos];
}

現在、c_str()/data()は次のように指定されていますoperator[]

§21.4.7 [string.accessors]

const charT* c_str() const noexcept;
const charT* data() const noexcept;

戻り値: for each inのpようなポインター。p + i == &operator[](i)i[0,size()]

これにより、上記のoperator[]実装はp + size() != &operator[](size()). ただし、ちょっとした工夫でこの問題を回避できます。

reference operator[](size_type pos){
  static contexpr charT default = charT();
  if(pos == size() && !evil_context) // assume 'volatile bool evil_context;'
    return default;
  return buf[pos];
}

struct evil_context_guard{
  volatile bool& ctx;
  evil_context_guard(volatile bool& b)
    : ctx(b) {}
  ~evil_context_guard(){ b = false; }
};

const charT* c_str() const noexcept{
  evil_context_guard g(evil_context = true);
  // now, during the call to 'c_str()', the requirement above holds
  // 'p + i == &operator[](i) for each i in [0,size()]'
  const charT* p = &buf[0];
  assert(p+size() == &operator[](size()));
  return p;
}

さて、明らかな質問は...

上記のコードは本当に準拠していますか、それとも何か見落としていますか?

4

2 に答える 2

4

与えられたコードを無視して、質問だけを考えると、

  • 残念ながら、答えは「はい」のようです。
  • それは確かに標準の意図ではありません。

したがって、それは欠陥のようです。

既知のライブラリの欠陥のリストを確認すると、この問題はまだ報告されていないようです。

チャットで述べたように、[comp.std.c++] に投稿することをお勧めします。これは、それが本当に欠陥であるかどうかの問題を解決し、そうであれば、欠陥リストに追加して修正するためです。

于 2012-08-04T15:47:21.633 に答える
0

どうすれば適合するのかわかりません。ユーザー コードは、約束された戻り値を観察することはできません。コード内のassertは間違った場所にあるため、誤解を招きます: 関数はまだ返されていません。戻り値:要件は、実装内の値ではなく、関数から返される値に適用されます (なぜそれが無意味な考えであるかは明らかです)。

アサーションは次の場所にあります。

auto p = s.c_str();
assert(p + s.size() == &operator[](s.size()));

特別に扱うという文言はs[s.size()]、ヌルターミネーターを爆破することを単に禁止することを意図していると思います。

于 2012-08-05T17:28:01.977 に答える