title: Small String Optimization on std::string from gcc 7
body: <p>I run a small test program to verify that our tool benefits from SSO:</p>
  
  <pre><code>// Example program
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  
  int main()
  {
      std::cout &lt;&lt; sizeof(std::string) &lt;&lt; " " &lt;&lt; std::string().capacity() &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>Now I am a little bit puzzled by the result: Why does std::string only have a short capacity of 15 bytes, but a memory size of 32? Since 1 byte is a tag, I'd expect a short string length of 31 bytes in that case. What happens to the remaining 16 bytes?</p>
  
  <p>edit: I have digged up the source code.</p>
  
  <pre><code>      struct _Alloc_hider : allocator_type // TODO check __is_final
        {
  #if __cplusplus &lt; 201103L
          _Alloc_hider(pointer __dat, const _Alloc&amp; __a = _Alloc())
          : allocator_type(__a), _M_p(__dat) { }
  #else
          _Alloc_hider(pointer __dat, const _Alloc&amp; __a)
          : allocator_type(__a), _M_p(__dat) { }
  
          _Alloc_hider(pointer __dat, _Alloc&amp;&amp; __a = _Alloc())
          : allocator_type(std::move(__a)), _M_p(__dat) { }
  #endif
  
          pointer _M_p; // The actual data.
        };
  
        _Alloc_hider      _M_dataplus;
        size_type         _M_string_length;
  
        enum { _S_local_capacity = 15 / sizeof(_CharT) };
  
        union
        {
          _CharT           _M_local_buf[_S_local_capacity + 1];
          size_type        _M_allocated_capacity;
        };
  </code></pre>
  
  <p>As you can see, the members _M_dataplus and _M_string_length are outside of the sso union. Together they take 16 bytes (8 for the pointer and 8 for the size). But why is it designed that way? Why not put _M_allocated_capacity into _Alloc_hider and make that part of the union.</p>