Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a std::string implementation conformant where 's.c_str() + s.size()' is not necessarily the same as '&s[s.size()]'?

§21.4.5 [string.access]

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

Returns: *(begin() + pos) if pos < size(). Otherwise, returns a reference to an object of type charT with value charT(), where modifying the object leads to undefined behavior.

The second part implies, to me atleast, that this "object of type charT" may reside outside of the sequence stored in the std::string object. Example implementation of a conforming operator[]:

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

Now, c_str()/data(), are specified in terms of operator[]:

§21.4.7 [string.accessors]

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

Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].

This would make the above operator[] implementation non-conformant, as p + size() != &operator[](size()). However, with a bit of trickery, you can circumvent this problem:

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;
}

Now, the obvious question is...

Is the above code really conformant or did I overlook something?

like image 202
Xeo Avatar asked Aug 04 '12 15:08

Xeo


1 Answers

Ignoring the given code, considering only the question, I think that

  • unfortunately, the answer seems to be “yes”, and
  • that is certainly not the intent of the standard.

Hence, it appears to be a defect.

Checking the list of known library defects apparently this issue has not yet been reported.

So, as I stated in chat, I recommend posting it to [comp.std.c++], in order to get resolved the question of whether it really is a defect, and if so, to get it into the defects list and fixed.

like image 99
Cheers and hth. - Alf Avatar answered Oct 20 '22 00:10

Cheers and hth. - Alf