Topic: a string type for APIs


Author: Roberto Hinz <robhz786@gmail.com>
Date: Wed, 24 Oct 2018 13:53:07 -0300
Raw View
--000000000000d314f60578fc52dc
Content-Type: text/plain; charset="UTF-8"

Hi,

Almost every API contains some functions that receive or return strings.
Yet, the C++ standard does not provide any good solution to transfer
strings across modules boundaries. While raw strings and
std::basic_string_view are not able to manage dynamic allocated memory,
std::basic_string does not have a standard ABI and its header is expensive
to compile.

Is there any effort to address this going on? If not, I would like to
propose the basic_api_string class template located at
https://github.com/robhz786/api_string. Its main characteristics are:

Pros:

   - Its header file is fast to compile.
   - It is able manage memory allocation/deallocation (using reference
   counting).
   - Its copy constructor is always fast and never throws.
   - It supports small string optimisation.
   - c_str() and data() member functions that always return a
   null-terminated raw string, *i.e.* they never return nullptr.
   - The user can create an basic_api_string object from a string literal
   without any memory allocating.
   - Can safely cross modules boundaries, because:
      - It has a specified ABI
      - It ensures that memory is deallocated in same module it has been
      allocated.

Cons:

   - No write access to individual characters ( like string_view ).
   - No support for char traits, allocators, nor reverse iterators ( to
   keep the header cheap to compile ).
   - No support for user defined character type. It must be char, char16_t,
   char32_t or wchar_t.

The <api_string> header

namespace std {
template <typename CharT> class basic_api_string {public:
    // Types
    using value_type      = CharT;
    using pointer         = const CharT*;
    using const_pointer   = const CharT*;
    using reference       = CharT&;
    using const_reference = const CharT&;
    using const_iterator  = const CharT*;
    using interator       = const CharT*;
    using size_type       = std::size_t;
    using difference_type = std::ptrdiff_t;

    // Construction and Destruction
    basic_api_string() noexcept;
    basic_api_string(const basic_api_string& other) noexcept;
    basic_api_string(basic_api_string&& other) noexcept;
    basic_api_string(const CharT* str, size_type count)
        [[expects: str != nullpr]];
    basic_api_string(const CharT* str)
        [[expects: str != nullpr]];

    ~basic_api_string();

    // Modifiers
    basic_api_string& operator=(const basic_api_string& other) noexcept;
    basic_api_string& operator=(basic_api_string&& other) noexcept;
    basic_api_string& operator=(const CharT* str)
        [[expects: str != nullpr]];
    void swap(basic_api_string& other) noexcept;
    void clear();

    // Capacity
    bool empty() const noexcept;
    size_type length() const noexcept;
    size_type size() const noexcept;

    // Element access
    const_pointer c_str() const noexcept
        [[ensures str: str != nullptr && str[length()] == CharT()]]
    const_pointer data() const noexcept;
        [[ensures str: str != nullptr && str[length()] == CharT()]]
    const_iterator cbegin() const noexcept;
    const_iterator begin() const noexcept;
    const_iterator cend() const noexcept;
    const_iterator end() const noexcept;
    const_reference operator[](size_type pos) const
        [[expects: pos <= length()]];
    const_reference at(size_type pos) const; // throws std::out_of_range
    const_reference front() const;
        [[expects: ! empty()]];
    const_reference back() const
        [[expects: ! empty()]];

    // Comparison
    int compare( const basic_api_string& other) const;
    int compare( size_type pos1
               , size_type count1
               , const basic_api_string& s ) const;  // throws std::out_of_rang
    int compare( size_type pos1
               , size_type count1
               , const basic_api_string& s
               , size_type pos2
               , size_type count2) const;  // throws std::out_of_rang
    int compare(const CharT* str) const
    int compare( size_type pos1
               , size_type count1
               , const CharT* s) const;
    int compare( size_type pos1
               , size_type count1
               , const CharT* s
               , size_type count2) const;
    bool starts_with(const basic_api_string& x) const;
    bool starts_with(CharT x) const;
    bool starts_with(const CharT* x) const;
    bool ends_with(const basic_api_string_view& x) const;
    bool ends_with(CharT x) const;
    bool ends_with(const CharT* x) const;};
template <class CharT> bool operator==(const basic_api_string<CharT>&,
const basic_api_string<CharT>&);template <class CharT> bool
operator!=(const basic_api_string<CharT>&, const
basic_api_string<CharT>&);template <class CharT> bool operator< (const
basic_api_string<CharT>&, const basic_api_string<CharT>&);template
<class CharT> bool operator<=(const basic_api_string<CharT>&, const
basic_api_string<CharT>&);template <class CharT> bool operator> (const
basic_api_string<CharT>&, const basic_api_string<CharT>&);template
<class CharT> bool operator>=(const basic_api_string<CharT>&, const
basic_api_string<CharT>&);
template <class CharT> bool operator==(const CharT*, const
basic_api_string<CharT>&);template <class CharT> bool operator!=(const
CharT*, const basic_api_string<CharT>&);template <class CharT> bool
operator< (const CharT*, const basic_api_string<CharT>&);template
<class CharT> bool operator<=(const CharT*, const
basic_api_string<CharT>&);template <class CharT> bool operator> (const
CharT*, const basic_api_string<CharT>&);template <class CharT> bool
operator>=(const CharT*, const basic_api_string<CharT>&);
template <class CharT> bool operator==(const basic_api_string<CharT>&,
const CharT*);template <class CharT> bool operator!=(const
basic_api_string<CharT>&, const CharT*);template <class CharT> bool
operator< (const basic_api_string<CharT>&, const CharT*);template
<class CharT> bool operator<=(const basic_api_string<CharT>&, const
CharT*);template <class CharT> bool operator> (const
basic_api_string<CharT>&, const CharT*);template <class CharT> bool
operator>=(const basic_api_string<CharT>&, const CharT*);

template <class CharT>
basic_api_string<CharT> api_string_ref(const CharT* s);
template <class CharT>
basic_api_string<CharT> api_string_ref(const CharT* s, std::size_t len)
    [[expects: s[len] == CharT()]];
namespace string_literals {

basic_api_string<char>     operator "" _as(const char* str, size_t
len) noexcept;
basic_api_string<char16_t> operator "" _as(const char16_t* str, size_t
len) noexcept;
basic_api_string<char32_t> operator "" _as(const char32_t* str, size_t
len) noexcept;
basic_api_string<wchar_t>  operator "" _as(const wchar_t* str, size_t
len) noexcept;
} // namespace string_literals
using api_string    = basic_api_string<char>;using api_u16string =
basic_api_string<char16_t>;using api_u32string =
basic_api_string<char32_t>;using api_wstring   =
basic_api_string<wchar_t>;
} // namespace std


   - The operator "" _as functions as well as the api_string_ref function
   templates create a basic_api_string object that just references a string
   without managing its lifetime.

The ABI

basic_api_string has no virtual functions. Its has the following internal
data structure:

union {
    constexpr static std::size_t sso_capacity()
    {
        constexpr std::size_t c = (2 * sizeof(void*)) / sizeof(CharT);
        return c > 0 ? (c - 1) : c;
    }

    struct {
        std::size_t len;
        std::__abi::api_string_mem_base* mem_manager; // see below
        const CharT* str;
    } big;

    struct { // (for small string optimization)
        unsigned char len;
        CharT str[sso_capacity() + 1];
    } small;};

The small object is used in SSO (small string optimization) mode. The big
object is used otherwise. We are in SSO mode, if, and only if, big.str ==
nullptr

   -

   when in SSO mode:
   - big.str must be null.
      - basic_api_string<CharT>::data() must return small.str.
      - small.len must not be greater than sso_capacity().
      - small.str[small.len] must be zero.
      - small.str[sso_capacity()] must be zero. Note that changing the
      value of small.str[sso_capacity()] corrupts big.str.
      - if small.len == 0 , then big.len must be zero too ( this
      facilitates the implementation of basic_api_string<CharT>::empty() )
   -

   when not in SSO mode:
   - big.str must not be null.
      - basic_api_string<CharT>::data() must return big.str.
      - big.str[big.len] must be zero.
      - If big.mem_manager != nullptr then the memory pointed by big.str is
      managed by reference counting, and big.mem_manager is used to update
      the counters ( see the api_string_mem_base below ).
      - If big.mem_manager == nullptr then the memory pointer by big.str is
      not managed by basic_api_string. This is the case when
      basic_api_string is created by api_string_ref function.

The api_string_mem_base class

struct api_string_mem_base;
struct api_string_func_table{
    typedef std::size_t (*func_size)(api_string_mem_base*);
    typedef void        (*func_void)(api_string_mem_base*);
    typedef bool        (*func_bool)(api_string_mem_base*);
    typedef std::byte*  (*func_ptr) (api_string_mem_base*);

    unsigned long abi_version = 0;
    func_size acquire = nullptr;
    func_void release = nullptr;
    func_bool unique  = nullptr;
    func_ptr  begin   = nullptr;
    func_ptr  end     = nullptr;};
struct api_string_mem_base{
    const api_string_func_table* const func_table;

    std::size_t acquire() { return func_table->acquire(this); }
    void release()        { func_table->release(this); }
    bool unique()         { return func_table->unique(this); }
    std::byte* begin()    { return func_table->begin(this); }
    std::byte* end()      { return func_table->end(this); }};


   - acquire() increments the reference counter, and returns the previous
   value
   - release() decrements the reference counter and, if it becames zero,
   deallocates the memory.
   - unique() tells whether the reretence countes is equal to one.
   - begin() and end() return the memory region that contains the string.
   - api_string_mem_base::abi_version shall be equall to zero.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9e5Kfy%2BTBtkRf-2i8EQ42Q5eRTQc0P9HLu9PP9UG4RCjg%40mail.gmail.com.

--000000000000d314f60578fc52dc
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_default" style=3D"font-family:arial,he=
lvetica,sans-serif"><div id=3D"m_4655701241357336627m_-203957810354332258gm=
ail-preview1" class=3D"m_4655701241357336627m_-203957810354332258gmail-g-b =
m_4655701241357336627m_-203957810354332258gmail-g-b--t1of2 m_46557012413573=
36627m_-203957810354332258gmail-split m_4655701241357336627m_-2039578103543=
32258gmail-split-preview">
  <div id=3D"m_4655701241357336627m_-203957810354332258gmail-preview" class=
=3D"m_4655701241357336627m_-203957810354332258gmail-preview-html"><p>Hi,<br=
></p><p>Almost
 every API contains some functions that receive or return strings. Yet,=20
the C++ standard does not provide any good solution to transfer strings=20
across modules boundaries. While raw strings and <code>std::basic_string_vi=
ew</code> are not able to manage dynamic allocated memory, <code>std::basic=
_string</code> does not have a standard ABI and its header is expensive to =
compile.</p>
<p>Is there any effort to address this going on? If not, I would like to pr=
opose the <code>basic_api_string</code> class template located at <a href=
=3D"https://github.com/robhz786/api_string" target=3D"_blank">https://githu=
b.com/robhz786/api_string</a>. Its main characteristics are:</p>
<p>Pros:</p>
<ul><li>Its header file is fast to compile.</li><li>It is able manage memor=
y allocation/deallocation (using reference counting).</li><li>Its copy cons=
tructor is always fast and never throws.</li><li>It supports small string o=
ptimisation.</li><li><code>c_str()</code> and <code>data()</code> member fu=
nctions that always return a null-terminated raw string, <i>i.e.</i> they n=
ever return <code>nullptr</code>.</li><li>The user can create an <code>basi=
c_api_string</code> object from a string literal without any memory allocat=
ing.</li><li>Can safely cross modules boundaries, because:
<ul><li>It has a specified ABI</li><li>It ensures that memory is deallocate=
d in same module it has been allocated.</li></ul>
</li></ul>
<p>Cons:</p>
<ul><li>No write access to individual characters ( like <code>string_view</=
code> ).</li><li>No support for char traits, allocators, nor reverse iterat=
ors ( to keep the header cheap to compile ).</li><li>No support for user de=
fined character type. It must be <code>char</code>, <code>char16_t</code>, =
<code>char32_t</code> or <code>wchar_t</code>.</li></ul><div><h2>The &lt;<c=
ode>api_string&gt;</code> header</h2>
<p>
</p><pre style=3D"color:rgb(0,0,32);background:rgb(246,248,255) none repeat=
 scroll 0% 0%"><span style=3D"color:rgb(32,0,128);font-weight:bold">namespa=
ce</span> <span style=3D"color:rgb(0,102,238)">std</span> <span style=3D"co=
lor:rgb(64,96,128)">{</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">typename</span> CharT<span style=3D"color:rgb(64,96,128=
)">&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">class</=
span> basic_api_string <span style=3D"color:rgb(64,96,128)">{</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">public</span><span sty=
le=3D"color:rgb(227,74,220)">:</span>
    <span style=3D"color:rgb(89,89,121)">// Types</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> value=
_type      <span style=3D"color:rgb(48,128,128)">=3D</span> CharT<span styl=
e=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> <span=
 style=3D"color:rgb(0,48,96)">pointer</span>         <span style=3D"color:r=
gb(48,128,128)">=3D</span> <span style=3D"color:rgb(32,0,128);font-weight:b=
old">const</span> CharT<span style=3D"color:rgb(48,128,128)">*</span><span =
style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> <span=
 style=3D"color:rgb(0,48,96)">const_pointer</span>   <span style=3D"color:r=
gb(48,128,128)">=3D</span> <span style=3D"color:rgb(32,0,128);font-weight:b=
old">const</span> CharT<span style=3D"color:rgb(48,128,128)">*</span><span =
style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> refer=
ence       <span style=3D"color:rgb(48,128,128)">=3D</span> CharT<span styl=
e=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"color:rgb(64,96,128)=
">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> const=
_reference <span style=3D"color:rgb(48,128,128)">=3D</span> <span style=3D"=
color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"colo=
r:rgb(48,128,128)">&amp;</span><span style=3D"color:rgb(64,96,128)">;</span=
>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> <span=
 style=3D"color:rgb(0,48,96)">const_iterator</span>  <span style=3D"color:r=
gb(48,128,128)">=3D</span> <span style=3D"color:rgb(32,0,128);font-weight:b=
old">const</span> CharT<span style=3D"color:rgb(48,128,128)">*</span><span =
style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> inter=
ator       <span style=3D"color:rgb(48,128,128)">=3D</span> <span style=3D"=
color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"colo=
r:rgb(48,128,128)">*</span><span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> size_=
type       <span style=3D"color:rgb(48,128,128)">=3D</span> <span style=3D"=
color:rgb(0,102,238)">std</span><span style=3D"color:rgb(64,96,128)">::</sp=
an><span style=3D"color:rgb(0,48,96)">size_t</span><span style=3D"color:rgb=
(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> diffe=
rence_type <span style=3D"color:rgb(48,128,128)">=3D</span> <span style=3D"=
color:rgb(0,102,238)">std</span><span style=3D"color:rgb(64,96,128)">::</sp=
an><span style=3D"color:rgb(0,48,96)">ptrdiff_t</span><span style=3D"color:=
rgb(64,96,128)">;</span>   =20

    <span style=3D"color:rgb(89,89,121)">// Construction and Destruction</s=
pan>
    basic_api_string<span style=3D"color:rgb(48,128,128)">(</span><span sty=
le=3D"color:rgb(48,128,128)">)</span> noexcept<span style=3D"color:rgb(64,9=
6,128)">;</span>
    basic_api_string<span style=3D"color:rgb(48,128,128)">(</span><span sty=
le=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<s=
pan style=3D"color:rgb(48,128,128)">&amp;</span> other<span style=3D"color:=
rgb(48,128,128)">)</span> noexcept<span style=3D"color:rgb(64,96,128)">;</s=
pan>
    basic_api_string<span style=3D"color:rgb(48,128,128)">(</span>basic_api=
_string<span style=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"col=
or:rgb(48,128,128)">&amp;</span> other<span style=3D"color:rgb(48,128,128)"=
>)</span> noexcept<span style=3D"color:rgb(64,96,128)">;</span>
    basic_api_string<span style=3D"color:rgb(48,128,128)">(</span><span sty=
le=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=
=3D"color:rgb(48,128,128)">*</span> str<span style=3D"color:rgb(48,128,128)=
">,</span> size_type <span style=3D"color:rgb(0,48,96)">count</span><span s=
tyle=3D"color:rgb(48,128,128)">)</span>
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>expects<span style=3D"color:rgb(64,96,128)">:</spa=
n> str <span style=3D"color:rgb(48,128,128)">!</span><span style=3D"color:r=
gb(48,128,128)">=3D</span> nullpr<span style=3D"color:rgb(48,128,128)">]</s=
pan><span style=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(=
64,96,128)">;</span>
    basic_api_string<span style=3D"color:rgb(48,128,128)">(</span><span sty=
le=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=
=3D"color:rgb(48,128,128)">*</span> str<span style=3D"color:rgb(48,128,128)=
">)</span>
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>expects<span style=3D"color:rgb(64,96,128)">:</spa=
n> str <span style=3D"color:rgb(48,128,128)">!</span><span style=3D"color:r=
gb(48,128,128)">=3D</span> nullpr<span style=3D"color:rgb(48,128,128)">]</s=
pan><span style=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(=
64,96,128)">;</span>

    <span style=3D"color:rgb(48,128,128)">~</span>basic_api_string<span sty=
le=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">=
)</span><span style=3D"color:rgb(64,96,128)">;</span>

    <span style=3D"color:rgb(89,89,121)">// Modifiers</span>
    basic_api_string<span style=3D"color:rgb(48,128,128)">&amp;</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span style=
=3D"color:rgb(48,128,128)">=3D</span><span style=3D"color:rgb(48,128,128)">=
(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> b=
asic_api_string<span style=3D"color:rgb(48,128,128)">&amp;</span> other<spa=
n style=3D"color:rgb(48,128,128)">)</span> noexcept<span style=3D"color:rgb=
(64,96,128)">;</span>
    basic_api_string<span style=3D"color:rgb(48,128,128)">&amp;</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span style=
=3D"color:rgb(48,128,128)">=3D</span><span style=3D"color:rgb(48,128,128)">=
(</span>basic_api_string<span style=3D"color:rgb(48,128,128)">&amp;</span><=
span style=3D"color:rgb(48,128,128)">&amp;</span> other<span style=3D"color=
:rgb(48,128,128)">)</span> noexcept<span style=3D"color:rgb(64,96,128)">;</=
span>
    basic_api_string<span style=3D"color:rgb(48,128,128)">&amp;</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span style=
=3D"color:rgb(48,128,128)">=3D</span><span style=3D"color:rgb(48,128,128)">=
(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> C=
harT<span style=3D"color:rgb(48,128,128)">*</span> str<span style=3D"color:=
rgb(48,128,128)">)</span>
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>expects<span style=3D"color:rgb(64,96,128)">:</spa=
n> str <span style=3D"color:rgb(48,128,128)">!</span><span style=3D"color:r=
gb(48,128,128)">=3D</span> nullpr<span style=3D"color:rgb(48,128,128)">]</s=
pan><span style=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(=
64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">void</span> <span =
style=3D"color:rgb(0,48,96)">swap</span><span style=3D"color:rgb(48,128,128=
)">(</span>basic_api_string<span style=3D"color:rgb(48,128,128)">&amp;</spa=
n> other<span style=3D"color:rgb(48,128,128)">)</span> noexcept<span style=
=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">void</span> clear<=
span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,12=
8,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span>

    <span style=3D"color:rgb(89,89,121)">// Capacity</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> empty<=
span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,12=
8,128)">)</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const=
</span> noexcept<span style=3D"color:rgb(64,96,128)">;</span>
    size_type length<span style=3D"color:rgb(48,128,128)">(</span><span sty=
le=3D"color:rgb(48,128,128)">)</span> <span style=3D"color:rgb(32,0,128);fo=
nt-weight:bold">const</span> noexcept<span style=3D"color:rgb(64,96,128)">;=
</span>
    size_type size<span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(48,128,128)">)</span> <span style=3D"color:rgb(32,0,128);font=
-weight:bold">const</span> noexcept<span style=3D"color:rgb(64,96,128)">;</=
span>

    <span style=3D"color:rgb(89,89,121)">// Element access</span>
    <span style=3D"color:rgb(0,48,96)">const_pointer</span> c_str<span styl=
e=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">)=
</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> n=
oexcept
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>ensures str<span style=3D"color:rgb(64,96,128)">:<=
/span> str <span style=3D"color:rgb(48,128,128)">!</span><span style=3D"col=
or:rgb(48,128,128)">=3D</span> <span style=3D"color:rgb(32,0,128);font-weig=
ht:bold">nullptr</span> <span style=3D"color:rgb(48,128,128)">&amp;</span><=
span style=3D"color:rgb(48,128,128)">&amp;</span> str<span style=3D"color:r=
gb(48,128,128)">[</span>length<span style=3D"color:rgb(48,128,128)">(</span=
><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(48,=
128,128)">]</span> <span style=3D"color:rgb(48,128,128)">=3D</span><span st=
yle=3D"color:rgb(48,128,128)">=3D</span> CharT<span style=3D"color:rgb(48,1=
28,128)">(</span><span style=3D"color:rgb(48,128,128)">)</span><span style=
=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(48,128,128)">]<=
/span>
    <span style=3D"color:rgb(0,48,96)">const_pointer</span> data<span style=
=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">)<=
/span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> no=
except<span style=3D"color:rgb(64,96,128)">;</span>
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>ensures str<span style=3D"color:rgb(64,96,128)">:<=
/span> str <span style=3D"color:rgb(48,128,128)">!</span><span style=3D"col=
or:rgb(48,128,128)">=3D</span> <span style=3D"color:rgb(32,0,128);font-weig=
ht:bold">nullptr</span> <span style=3D"color:rgb(48,128,128)">&amp;</span><=
span style=3D"color:rgb(48,128,128)">&amp;</span> str<span style=3D"color:r=
gb(48,128,128)">[</span>length<span style=3D"color:rgb(48,128,128)">(</span=
><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(48,=
128,128)">]</span> <span style=3D"color:rgb(48,128,128)">=3D</span><span st=
yle=3D"color:rgb(48,128,128)">=3D</span> CharT<span style=3D"color:rgb(48,1=
28,128)">(</span><span style=3D"color:rgb(48,128,128)">)</span><span style=
=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(48,128,128)">]<=
/span>
    <span style=3D"color:rgb(0,48,96)">const_iterator</span> cbegin<span st=
yle=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)"=
>)</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span>=
 noexcept<span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(0,48,96)">const_iterator</span> begin<span sty=
le=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">=
)</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> =
noexcept<span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(0,48,96)">const_iterator</span> cend<span styl=
e=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">)=
</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> n=
oexcept<span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(0,48,96)">const_iterator</span> end<span style=
=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">)<=
/span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> no=
except<span style=3D"color:rgb(64,96,128)">;</span>
    const_reference <span style=3D"color:rgb(32,0,128);font-weight:bold">op=
erator</span><span style=3D"color:rgb(48,128,128)">[</span><span style=3D"c=
olor:rgb(48,128,128)">]</span><span style=3D"color:rgb(48,128,128)">(</span=
>size_type pos<span style=3D"color:rgb(48,128,128)">)</span> <span style=3D=
"color:rgb(32,0,128);font-weight:bold">const</span>
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>expects<span style=3D"color:rgb(64,96,128)">:</spa=
n> pos <span style=3D"color:rgb(48,128,128)">&lt;</span><span style=3D"colo=
r:rgb(48,128,128)">=3D</span> length<span style=3D"color:rgb(48,128,128)">(=
</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:r=
gb(48,128,128)">]</span><span style=3D"color:rgb(48,128,128)">]</span><span=
 style=3D"color:rgb(64,96,128)">;</span>
    const_reference at<span style=3D"color:rgb(48,128,128)">(</span>size_ty=
pe pos<span style=3D"color:rgb(48,128,128)">)</span> <span style=3D"color:r=
gb(32,0,128);font-weight:bold">const</span><span style=3D"color:rgb(64,96,1=
28)">;</span> <span style=3D"color:rgb(89,89,121)">// throws std::out_of_ra=
nge</span>
    const_reference front<span style=3D"color:rgb(48,128,128)">(</span><spa=
n style=3D"color:rgb(48,128,128)">)</span> <span style=3D"color:rgb(32,0,12=
8);font-weight:bold">const</span><span style=3D"color:rgb(64,96,128)">;</sp=
an>
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>expects<span style=3D"color:rgb(64,96,128)">:</spa=
n> <span style=3D"color:rgb(48,128,128)">!</span> empty<span style=3D"color=
:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">)</span><sp=
an style=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(48,128,=
128)">]</span><span style=3D"color:rgb(64,96,128)">;</span>
    const_reference back<span style=3D"color:rgb(48,128,128)">(</span><span=
 style=3D"color:rgb(48,128,128)">)</span> <span style=3D"color:rgb(32,0,128=
);font-weight:bold">const</span>
        <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:=
rgb(48,128,128)">[</span>expects<span style=3D"color:rgb(64,96,128)">:</spa=
n> <span style=3D"color:rgb(48,128,128)">!</span> empty<span style=3D"color=
:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">)</span><sp=
an style=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(48,128,=
128)">]</span><span style=3D"color:rgb(64,96,128)">;</span>

    <span style=3D"color:rgb(89,89,121)">// Comparison</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">int</span> compare=
<span style=3D"color:rgb(48,128,128)">(</span> <span style=3D"color:rgb(32,=
0,128);font-weight:bold">const</span> basic_api_string<span style=3D"color:=
rgb(48,128,128)">&amp;</span> other<span style=3D"color:rgb(48,128,128)">)<=
/span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span><sp=
an style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">int</span> compare=
<span style=3D"color:rgb(48,128,128)">(</span> size_type pos1
               <span style=3D"color:rgb(48,128,128)">,</span> size_type cou=
nt1
               <span style=3D"color:rgb(48,128,128)">,</span> <span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(48,128,128)">&amp;</span> s <span style=3D"color:rgb(4=
8,128,128)">)</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">c=
onst</span><span style=3D"color:rgb(64,96,128)">;</span>  <span style=3D"co=
lor:rgb(89,89,121)">// throws std::out_of_rang</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">int</span> compare=
<span style=3D"color:rgb(48,128,128)">(</span> size_type pos1
               <span style=3D"color:rgb(48,128,128)">,</span> size_type cou=
nt1
               <span style=3D"color:rgb(48,128,128)">,</span> <span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(48,128,128)">&amp;</span> s
               <span style=3D"color:rgb(48,128,128)">,</span> size_type pos=
2
               <span style=3D"color:rgb(48,128,128)">,</span> size_type cou=
nt2<span style=3D"color:rgb(48,128,128)">)</span> <span style=3D"color:rgb(=
32,0,128);font-weight:bold">const</span><span style=3D"color:rgb(64,96,128)=
">;</span>  <span style=3D"color:rgb(89,89,121)">// throws std::out_of_rang=
</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">int</span> compare=
<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(32,0=
,128);font-weight:bold">const</span> CharT<span style=3D"color:rgb(48,128,1=
28)">*</span> str<span style=3D"color:rgb(48,128,128)">)</span> <span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">int</span> compare=
<span style=3D"color:rgb(48,128,128)">(</span> size_type pos1
               <span style=3D"color:rgb(48,128,128)">,</span> size_type cou=
nt1
               <span style=3D"color:rgb(48,128,128)">,</span> <span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"=
color:rgb(48,128,128)">*</span> s<span style=3D"color:rgb(48,128,128)">)</s=
pan> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span><span=
 style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">int</span> compare=
<span style=3D"color:rgb(48,128,128)">(</span> size_type pos1
               <span style=3D"color:rgb(48,128,128)">,</span> size_type cou=
nt1
               <span style=3D"color:rgb(48,128,128)">,</span> <span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"=
color:rgb(48,128,128)">*</span> s
               <span style=3D"color:rgb(48,128,128)">,</span> size_type cou=
nt2<span style=3D"color:rgb(48,128,128)">)</span> <span style=3D"color:rgb(=
32,0,128);font-weight:bold">const</span><span style=3D"color:rgb(64,96,128)=
">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> starts=
_with<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb=
(32,0,128);font-weight:bold">const</span> basic_api_string<span style=3D"co=
lor:rgb(48,128,128)">&amp;</span> x<span style=3D"color:rgb(48,128,128)">)<=
/span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span><sp=
an style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> starts=
_with<span style=3D"color:rgb(48,128,128)">(</span>CharT x<span style=3D"co=
lor:rgb(48,128,128)">)</span> <span style=3D"color:rgb(32,0,128);font-weigh=
t:bold">const</span><span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> starts=
_with<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb=
(32,0,128);font-weight:bold">const</span> CharT<span style=3D"color:rgb(48,=
128,128)">*</span> x<span style=3D"color:rgb(48,128,128)">)</span> <span st=
yle=3D"color:rgb(32,0,128);font-weight:bold">const</span><span style=3D"col=
or:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> ends_w=
ith<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(3=
2,0,128);font-weight:bold">const</span> basic_api_string_view<span style=3D=
"color:rgb(48,128,128)">&amp;</span> x<span style=3D"color:rgb(48,128,128)"=
>)</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span>=
<span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> ends_w=
ith<span style=3D"color:rgb(48,128,128)">(</span>CharT x<span style=3D"colo=
r:rgb(48,128,128)">)</span> <span style=3D"color:rgb(32,0,128);font-weight:=
bold">const</span><span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> ends_w=
ith<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(3=
2,0,128);font-weight:bold">const</span> CharT<span style=3D"color:rgb(48,12=
8,128)">*</span> x<span style=3D"color:rgb(48,128,128)">)</span> <span styl=
e=3D"color:rgb(32,0,128);font-weight:bold">const</span><span style=3D"color=
:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(64,96,128)">}</span><span style=3D"color:rgb(64,96=
,128)">;</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">=3D</span><span style=3D"color:rgb(48,128,=
128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(6=
4,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><sp=
an style=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,1=
28);font-weight:bold">const</span> basic_api_string<span style=3D"color:rgb=
(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(64,96,128)">&gt;</spa=
n><span style=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"color:rg=
b(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">!</span><span style=3D"color:rgb(48,128,12=
8)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=3D"=
color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<span st=
yle=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(64,96=
,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><span s=
tyle=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,128);=
font-weight:bold">const</span> basic_api_string<span style=3D"color:rgb(64,=
96,128)">&lt;</span>CharT<span style=3D"color:rgb(64,96,128)">&gt;</span><s=
pan style=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"color:rgb(48=
,128,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&lt;</span> <span style=3D"color:rgb(48,12=
8,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const<=
/span> basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>Char=
T<span style=3D"color:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(4=
8,128,128)">&amp;</span><span style=3D"color:rgb(48,128,128)">,</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_str=
ing<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"colo=
r:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</s=
pan><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(=
64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&lt;</span><span style=3D"color:rgb(48,128=
,128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(6=
4,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><sp=
an style=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,1=
28);font-weight:bold">const</span> basic_api_string<span style=3D"color:rgb=
(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(64,96,128)">&gt;</spa=
n><span style=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"color:rg=
b(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&gt;</span> <span style=3D"color:rgb(48,12=
8,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const<=
/span> basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>Char=
T<span style=3D"color:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(4=
8,128,128)">&amp;</span><span style=3D"color:rgb(48,128,128)">,</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_str=
ing<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"colo=
r:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</s=
pan><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(=
64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&gt;</span><span style=3D"color:rgb(48,128=
,128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(6=
4,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><sp=
an style=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,1=
28);font-weight:bold">const</span> basic_api_string<span style=3D"color:rgb=
(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(64,96,128)">&gt;</spa=
n><span style=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"color:rg=
b(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">=3D</span><span style=3D"color:rgb(48,128,=
128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"=
color:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">,</spa=
n> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_=
api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=
=3D"color:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">=
&amp;</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"co=
lor:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">!</span><span style=3D"color:rgb(48,128,12=
8)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=3D"=
color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"colo=
r:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">,</span> <=
span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_=
string<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"c=
olor:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;=
</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:r=
gb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&lt;</span> <span style=3D"color:rgb(48,12=
8,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const<=
/span> CharT<span style=3D"color:rgb(48,128,128)">*</span><span style=3D"co=
lor:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,128);font-weigh=
t:bold">const</span> basic_api_string<span style=3D"color:rgb(64,96,128)">&=
lt;</span>CharT<span style=3D"color:rgb(64,96,128)">&gt;</span><span style=
=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"color:rgb(48,128,128)=
">)</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&lt;</span><span style=3D"color:rgb(48,128=
,128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"=
color:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">,</spa=
n> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_=
api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=
=3D"color:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">=
&amp;</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"co=
lor:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&gt;</span> <span style=3D"color:rgb(48,12=
8,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const<=
/span> CharT<span style=3D"color:rgb(48,128,128)">*</span><span style=3D"co=
lor:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,128);font-weigh=
t:bold">const</span> basic_api_string<span style=3D"color:rgb(64,96,128)">&=
lt;</span>CharT<span style=3D"color:rgb(64,96,128)">&gt;</span><span style=
=3D"color:rgb(48,128,128)">&amp;</span><span style=3D"color:rgb(48,128,128)=
">)</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&gt;</span><span style=3D"color:rgb(48,128=
,128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span style=3D"=
color:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">,</spa=
n> <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_=
api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=
=3D"color:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">=
&amp;</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"co=
lor:rgb(64,96,128)">;</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">=3D</span><span style=3D"color:rgb(48,128,=
128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(6=
4,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><sp=
an style=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,1=
28);font-weight:bold">const</span> CharT<span style=3D"color:rgb(48,128,128=
)">*</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"col=
or:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">!</span><span style=3D"color:rgb(48,128,12=
8)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=3D"=
color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<span st=
yle=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(64,96=
,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><span s=
tyle=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,128);=
font-weight:bold">const</span> CharT<span style=3D"color:rgb(48,128,128)">*=
</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:r=
gb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&lt;</span> <span style=3D"color:rgb(48,12=
8,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const<=
/span> basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>Char=
T<span style=3D"color:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(4=
8,128,128)">&amp;</span><span style=3D"color:rgb(48,128,128)">,</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span st=
yle=3D"color:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)"=
>)</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&lt;</span><span style=3D"color:rgb(48,128=
,128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(6=
4,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><sp=
an style=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,1=
28);font-weight:bold">const</span> CharT<span style=3D"color:rgb(48,128,128=
)">*</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"col=
or:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&gt;</span> <span style=3D"color:rgb(48,12=
8,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">const<=
/span> basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>Char=
T<span style=3D"color:rgb(64,96,128)">&gt;</span><span style=3D"color:rgb(4=
8,128,128)">&amp;</span><span style=3D"color:rgb(48,128,128)">,</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">const</span> CharT<span st=
yle=3D"color:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)"=
>)</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">operator</span><span=
 style=3D"color:rgb(48,128,128)">&gt;</span><span style=3D"color:rgb(48,128=
,128)">=3D</span><span style=3D"color:rgb(48,128,128)">(</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> basic_api_string<spa=
n style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span style=3D"color:rgb(6=
4,96,128)">&gt;</span><span style=3D"color:rgb(48,128,128)">&amp;</span><sp=
an style=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(32,0,1=
28);font-weight:bold">const</span> CharT<span style=3D"color:rgb(48,128,128=
)">*</span><span style=3D"color:rgb(48,128,128)">)</span><span style=3D"col=
or:rgb(64,96,128)">;</span>


<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span>
basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span =
style=3D"color:rgb(64,96,128)">&gt;</span> api_string_ref<span style=3D"col=
or:rgb(48,128,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:=
bold">const</span> CharT<span style=3D"color:rgb(48,128,128)">*</span> s<sp=
an style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(64,96,1=
28)">;</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">template</span> <span =
style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,128=
);font-weight:bold">class</span> CharT<span style=3D"color:rgb(64,96,128)">=
&gt;</span>
basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>CharT<span =
style=3D"color:rgb(64,96,128)">&gt;</span> api_string_ref<span style=3D"col=
or:rgb(48,128,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:=
bold">const</span> CharT<span style=3D"color:rgb(48,128,128)">*</span> s<sp=
an style=3D"color:rgb(48,128,128)">,</span> <span style=3D"color:rgb(0,102,=
238)">std</span><span style=3D"color:rgb(64,96,128)">::</span><span style=
=3D"color:rgb(0,48,96)">size_t</span> len<span style=3D"color:rgb(48,128,12=
8)">)</span>
    <span style=3D"color:rgb(48,128,128)">[</span><span style=3D"color:rgb(=
48,128,128)">[</span>expects<span style=3D"color:rgb(64,96,128)">:</span> s=
<span style=3D"color:rgb(48,128,128)">[</span>len<span style=3D"color:rgb(4=
8,128,128)">]</span> <span style=3D"color:rgb(48,128,128)">=3D</span><span =
style=3D"color:rgb(48,128,128)">=3D</span> CharT<span style=3D"color:rgb(48=
,128,128)">(</span><span style=3D"color:rgb(48,128,128)">)</span><span styl=
e=3D"color:rgb(48,128,128)">]</span><span style=3D"color:rgb(48,128,128)">]=
</span><span style=3D"color:rgb(64,96,128)">;</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">namespace</span> strin=
g_literals <span style=3D"color:rgb(64,96,128)">{</span>

basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">char</span><span style=3D"color:r=
gb(64,96,128)">&gt;</span>     <span style=3D"color:rgb(32,0,128);font-weig=
ht:bold">operator</span> <span style=3D"color:rgb(128,0,0)">&quot;</span><s=
pan style=3D"color:rgb(128,0,0)">&quot;</span> _as<span style=3D"color:rgb(=
48,128,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">c=
onst</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">char</span=
><span style=3D"color:rgb(48,128,128)">*</span> str<span style=3D"color:rgb=
(48,128,128)">,</span> <span style=3D"color:rgb(0,48,96)">size_t</span> len=
<span style=3D"color:rgb(48,128,128)">)</span> noexcept<span style=3D"color=
:rgb(64,96,128)">;</span>
basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>char16_t<sp=
an style=3D"color:rgb(64,96,128)">&gt;</span> <span style=3D"color:rgb(32,0=
,128);font-weight:bold">operator</span> <span style=3D"color:rgb(128,0,0)">=
&quot;</span><span style=3D"color:rgb(128,0,0)">&quot;</span> _as<span styl=
e=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(32,0,128);font=
-weight:bold">const</span> char16_t<span style=3D"color:rgb(48,128,128)">*<=
/span> str<span style=3D"color:rgb(48,128,128)">,</span> <span style=3D"col=
or:rgb(0,48,96)">size_t</span> len<span style=3D"color:rgb(48,128,128)">)</=
span> noexcept<span style=3D"color:rgb(64,96,128)">;</span>
basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span>char32_t<sp=
an style=3D"color:rgb(64,96,128)">&gt;</span> <span style=3D"color:rgb(32,0=
,128);font-weight:bold">operator</span> <span style=3D"color:rgb(128,0,0)">=
&quot;</span><span style=3D"color:rgb(128,0,0)">&quot;</span> _as<span styl=
e=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(32,0,128);font=
-weight:bold">const</span> char32_t<span style=3D"color:rgb(48,128,128)">*<=
/span> str<span style=3D"color:rgb(48,128,128)">,</span> <span style=3D"col=
or:rgb(0,48,96)">size_t</span> len<span style=3D"color:rgb(48,128,128)">)</=
span> noexcept<span style=3D"color:rgb(64,96,128)">;</span>
basic_api_string<span style=3D"color:rgb(64,96,128)">&lt;</span><span style=
=3D"color:rgb(32,0,128);font-weight:bold">wchar_t</span><span style=3D"colo=
r:rgb(64,96,128)">&gt;</span>  <span style=3D"color:rgb(32,0,128);font-weig=
ht:bold">operator</span> <span style=3D"color:rgb(128,0,0)">&quot;</span><s=
pan style=3D"color:rgb(128,0,0)">&quot;</span> _as<span style=3D"color:rgb(=
48,128,128)">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">c=
onst</span> <span style=3D"color:rgb(32,0,128);font-weight:bold">wchar_t</s=
pan><span style=3D"color:rgb(48,128,128)">*</span> str<span style=3D"color:=
rgb(48,128,128)">,</span> <span style=3D"color:rgb(0,48,96)">size_t</span> =
len<span style=3D"color:rgb(48,128,128)">)</span> noexcept<span style=3D"co=
lor:rgb(64,96,128)">;</span>

<span style=3D"color:rgb(64,96,128)">}</span> <span style=3D"color:rgb(89,8=
9,121)">// namespace string_literals</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> api_strin=
g    <span style=3D"color:rgb(48,128,128)">=3D</span> basic_api_string<span=
 style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,12=
8);font-weight:bold">char</span><span style=3D"color:rgb(64,96,128)">&gt;</=
span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> api_u16st=
ring <span style=3D"color:rgb(48,128,128)">=3D</span> basic_api_string<span=
 style=3D"color:rgb(64,96,128)">&lt;</span>char16_t<span style=3D"color:rgb=
(64,96,128)">&gt;</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> api_u32st=
ring <span style=3D"color:rgb(48,128,128)">=3D</span> basic_api_string<span=
 style=3D"color:rgb(64,96,128)">&lt;</span>char32_t<span style=3D"color:rgb=
(64,96,128)">&gt;</span><span style=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(32,0,128);font-weight:bold">using</span> api_wstri=
ng   <span style=3D"color:rgb(48,128,128)">=3D</span> basic_api_string<span=
 style=3D"color:rgb(64,96,128)">&lt;</span><span style=3D"color:rgb(32,0,12=
8);font-weight:bold">wchar_t</span><span style=3D"color:rgb(64,96,128)">&gt=
;</span><span style=3D"color:rgb(64,96,128)">;</span>

<span style=3D"color:rgb(64,96,128)">}</span> <span style=3D"color:rgb(89,8=
9,121)">// namespace std</span>
</pre><ul><li>The <code>operator &quot;&quot; _as</code> functions as well =
as the <code>api_string_ref</code> function templates create a <code>basic_=
api_string</code> object that just references a string without managing its=
 lifetime.</li></ul>
<h1><code></code></h1><div><h2>The ABI<code></code></h2></div>
<p><code>basic_api_string</code> has no virtual functions. Its has the foll=
owing internal data structure:</p><p>
</p><pre style=3D"color:rgb(0,0,32);background:rgb(246,248,255) none repeat=
 scroll 0% 0%"><span style=3D"color:rgb(32,0,128);font-weight:bold">union</=
span> <span style=3D"color:rgb(64,96,128)">{</span>
    constexpr <span style=3D"color:rgb(32,0,128);font-weight:bold">static</=
span> <span style=3D"color:rgb(0,102,238)">std</span><span style=3D"color:r=
gb(64,96,128)">::</span><span style=3D"color:rgb(0,48,96)">size_t</span> ss=
o_capacity<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"colo=
r:rgb(48,128,128)">)</span>
    <span style=3D"color:rgb(64,96,128)">{</span>
        constexpr <span style=3D"color:rgb(0,102,238)">std</span><span styl=
e=3D"color:rgb(64,96,128)">::</span><span style=3D"color:rgb(0,48,96)">size=
_t</span> c <span style=3D"color:rgb(48,128,128)">=3D</span> <span style=3D=
"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(0,140,0)">2</span>=
 <span style=3D"color:rgb(48,128,128)">*</span> <span style=3D"color:rgb(32=
,0,128);font-weight:bold">sizeof</span><span style=3D"color:rgb(48,128,128)=
">(</span><span style=3D"color:rgb(32,0,128);font-weight:bold">void</span><=
span style=3D"color:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,12=
8,128)">)</span><span style=3D"color:rgb(48,128,128)">)</span> <span style=
=3D"color:rgb(48,128,128)">/</span> <span style=3D"color:rgb(32,0,128);font=
-weight:bold">sizeof</span><span style=3D"color:rgb(48,128,128)">(</span>Ch=
arT<span style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(6=
4,96,128)">;</span>
        <span style=3D"color:rgb(32,0,128);font-weight:bold">return</span> =
c <span style=3D"color:rgb(48,128,128)">&gt;</span> <span style=3D"color:rg=
b(0,140,0)">0</span> <span style=3D"color:rgb(64,96,128)">?</span> <span st=
yle=3D"color:rgb(48,128,128)">(</span>c <span style=3D"color:rgb(48,128,128=
)">-</span> <span style=3D"color:rgb(0,140,0)">1</span><span style=3D"color=
:rgb(48,128,128)">)</span> <span style=3D"color:rgb(64,96,128)">:</span> c<=
span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(64,96,128)">}</span>

    <span style=3D"color:rgb(32,0,128);font-weight:bold">struct</span> <spa=
n style=3D"color:rgb(64,96,128)">{</span>
        <span style=3D"color:rgb(0,102,238)">std</span><span style=3D"color=
:rgb(64,96,128)">::</span><span style=3D"color:rgb(0,48,96)">size_t</span> =
len<span style=3D"color:rgb(64,96,128)">;</span>
        <span style=3D"color:rgb(0,102,238)">std</span><span style=3D"color=
:rgb(64,96,128)">::</span>__abi<span style=3D"color:rgb(64,96,128)">::</spa=
n>api_string_mem_base<span style=3D"color:rgb(48,128,128)">*</span> mem_man=
ager<span style=3D"color:rgb(64,96,128)">;</span> <span style=3D"color:rgb(=
89,89,121)">// see below</span>
        <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> C=
harT<span style=3D"color:rgb(48,128,128)">*</span> str<span style=3D"color:=
rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(64,96,128)">}</span> big<span style=3D"color:r=
gb(64,96,128)">;</span>

    <span style=3D"color:rgb(32,0,128);font-weight:bold">struct</span> <spa=
n style=3D"color:rgb(64,96,128)">{</span> <span style=3D"color:rgb(89,89,12=
1)">// (for small string optimization)</span>
        <span style=3D"color:rgb(32,0,128);font-weight:bold">unsigned</span=
> <span style=3D"color:rgb(32,0,128);font-weight:bold">char</span> len<span=
 style=3D"color:rgb(64,96,128)">;</span>
        CharT str<span style=3D"color:rgb(48,128,128)">[</span>sso_capacity=
<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,1=
28,128)">)</span> <span style=3D"color:rgb(48,128,128)">+</span> <span styl=
e=3D"color:rgb(0,140,0)">1</span><span style=3D"color:rgb(48,128,128)">]</s=
pan><span style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(64,96,128)">}</span> small<span style=3D"color=
:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(64,96,128)">}</span><span style=3D"color:rgb(64,96=
,128)">;</span>
</pre>
<p></p>The <code>small</code> object is used in SSO (small string optimizat=
ion) mode. The <code>big</code> object is used otherwise. We are in SSO mod=
e, if, and only if, <code>big.str =3D=3D nullptr</code>
<ul><li>
<p>when in SSO mode:</p>
<ul><li><code>big.str</code> must be null.</li><li><code>basic_api_string&l=
t;CharT&gt;::data()</code> must return <code>small.str</code>.</li><li><cod=
e>small.len</code> must not be greater than <code>sso_capacity()</code>.</l=
i><li><code>small.str[small.len]</code> must be zero.</li><li><code>small.s=
tr[sso_capacity()]</code> must be zero. Note that changing the value of <co=
de>small.str[sso_capacity()]</code> corrupts <code>big.str</code>.</li><li>=
if <code>small.len =3D=3D 0</code> , then <code>big.len</code> must be zero=
 too ( this facilitates the implementation of <code>basic_api_string&lt;Cha=
rT&gt;::empty()</code> )</li></ul>
</li><li>
<p>when not in SSO mode:</p>
<ul><li><code>big.str</code> must not be null.</li><li><code>basic_api_stri=
ng&lt;CharT&gt;::data()</code> must return <code>big.str</code>.</li><li><c=
ode>big.str[big.len]</code> must be zero.</li><li>If <code>big.mem_manager =
!=3D nullptr</code> then the memory pointed by <code>big.str</code> is mana=
ged by reference counting, and <code>big.mem_manager</code> is used to upda=
te the counters ( see the <code>api_string_mem_base</code> below ).</li><li=
>If <code>big.mem_manager =3D=3D nullptr</code> then the memory pointer by =
<code>big.str</code> is not managed by <code>basic_api_string</code>. This =
is the case when <code>basic_api_string</code> is created by <code>api_stri=
ng_ref</code> function.</li></ul>
</li></ul>
<h3>The <code>api_string_mem_base</code> class</h3>
<pre style=3D"color:rgb(0,0,32);background:rgb(246,248,255) none repeat scr=
oll 0% 0%"><span style=3D"color:rgb(32,0,128);font-weight:bold">struct</spa=
n> api_string_mem_base<span style=3D"color:rgb(64,96,128)">;</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">struct</span> api_stri=
ng_func_table
<span style=3D"color:rgb(64,96,128)">{</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">typedef</span> <sp=
an style=3D"color:rgb(0,102,238)">std</span><span style=3D"color:rgb(64,96,=
128)">::</span><span style=3D"color:rgb(0,48,96)">size_t</span> <span style=
=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)">*<=
/span>func_size<span style=3D"color:rgb(48,128,128)">)</span><span style=3D=
"color:rgb(48,128,128)">(</span>api_string_mem_base<span style=3D"color:rgb=
(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">)</span><span s=
tyle=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">typedef</span> <sp=
an style=3D"color:rgb(32,0,128);font-weight:bold">void</span>        <span =
style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128=
)">*</span>func_void<span style=3D"color:rgb(48,128,128)">)</span><span sty=
le=3D"color:rgb(48,128,128)">(</span>api_string_mem_base<span style=3D"colo=
r:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">)</span><s=
pan style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">typedef</span> <sp=
an style=3D"color:rgb(32,0,128);font-weight:bold">bool</span>        <span =
style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128=
)">*</span>func_bool<span style=3D"color:rgb(48,128,128)">)</span><span sty=
le=3D"color:rgb(48,128,128)">(</span>api_string_mem_base<span style=3D"colo=
r:rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">)</span><s=
pan style=3D"color:rgb(64,96,128)">;</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">typedef</span> <sp=
an style=3D"color:rgb(0,102,238)">std</span><span style=3D"color:rgb(64,96,=
128)">::</span>byte<span style=3D"color:rgb(48,128,128)">*</span>  <span st=
yle=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,128,128)"=
>*</span>func_ptr<span style=3D"color:rgb(48,128,128)">)</span> <span style=
=3D"color:rgb(48,128,128)">(</span>api_string_mem_base<span style=3D"color:=
rgb(48,128,128)">*</span><span style=3D"color:rgb(48,128,128)">)</span><spa=
n style=3D"color:rgb(64,96,128)">;</span>

    <span style=3D"color:rgb(32,0,128);font-weight:bold">unsigned</span> <s=
pan style=3D"color:rgb(32,0,128);font-weight:bold">long</span> abi_version =
<span style=3D"color:rgb(48,128,128)">=3D</span> <span style=3D"color:rgb(0=
,140,0)">0</span><span style=3D"color:rgb(64,96,128)">;</span>
    func_size acquire <span style=3D"color:rgb(48,128,128)">=3D</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">nullptr</span><span style=
=3D"color:rgb(64,96,128)">;</span>
    func_void release <span style=3D"color:rgb(48,128,128)">=3D</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">nullptr</span><span style=
=3D"color:rgb(64,96,128)">;</span>
    func_bool <span style=3D"color:rgb(0,48,96)">unique</span>  <span style=
=3D"color:rgb(48,128,128)">=3D</span> <span style=3D"color:rgb(32,0,128);fo=
nt-weight:bold">nullptr</span><span style=3D"color:rgb(64,96,128)">;</span>
    func_ptr  begin   <span style=3D"color:rgb(48,128,128)">=3D</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">nullptr</span><span style=
=3D"color:rgb(64,96,128)">;</span>
    func_ptr  end     <span style=3D"color:rgb(48,128,128)">=3D</span> <spa=
n style=3D"color:rgb(32,0,128);font-weight:bold">nullptr</span><span style=
=3D"color:rgb(64,96,128)">;</span>
<span style=3D"color:rgb(64,96,128)">}</span><span style=3D"color:rgb(64,96=
,128)">;</span>

<span style=3D"color:rgb(32,0,128);font-weight:bold">struct</span> api_stri=
ng_mem_base
<span style=3D"color:rgb(64,96,128)">{</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">const</span> api_s=
tring_func_table<span style=3D"color:rgb(48,128,128)">*</span> <span style=
=3D"color:rgb(32,0,128);font-weight:bold">const</span> func_table<span styl=
e=3D"color:rgb(64,96,128)">;</span>

    <span style=3D"color:rgb(0,102,238)">std</span><span style=3D"color:rgb=
(64,96,128)">::</span><span style=3D"color:rgb(0,48,96)">size_t</span> acqu=
ire<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(4=
8,128,128)">)</span> <span style=3D"color:rgb(64,96,128)">{</span> <span st=
yle=3D"color:rgb(32,0,128);font-weight:bold">return</span> func_table<span =
style=3D"color:rgb(48,128,128)">-</span><span style=3D"color:rgb(48,128,128=
)">&gt;</span>acquire<span style=3D"color:rgb(48,128,128)">(</span><span st=
yle=3D"color:rgb(32,0,128);font-weight:bold">this</span><span style=3D"colo=
r:rgb(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span> <s=
pan style=3D"color:rgb(64,96,128)">}</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">void</span> releas=
e<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,=
128,128)">)</span>        <span style=3D"color:rgb(64,96,128)">{</span> fun=
c_table<span style=3D"color:rgb(48,128,128)">-</span><span style=3D"color:r=
gb(48,128,128)">&gt;</span>release<span style=3D"color:rgb(48,128,128)">(</=
span><span style=3D"color:rgb(32,0,128);font-weight:bold">this</span><span =
style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)=
">;</span> <span style=3D"color:rgb(64,96,128)">}</span>
    <span style=3D"color:rgb(32,0,128);font-weight:bold">bool</span> <span =
style=3D"color:rgb(0,48,96)">unique</span><span style=3D"color:rgb(48,128,1=
28)">(</span><span style=3D"color:rgb(48,128,128)">)</span>         <span s=
tyle=3D"color:rgb(64,96,128)">{</span> <span style=3D"color:rgb(32,0,128);f=
ont-weight:bold">return</span> func_table<span style=3D"color:rgb(48,128,12=
8)">-</span><span style=3D"color:rgb(48,128,128)">&gt;</span><span style=3D=
"color:rgb(0,48,96)">unique</span><span style=3D"color:rgb(48,128,128)">(</=
span><span style=3D"color:rgb(32,0,128);font-weight:bold">this</span><span =
style=3D"color:rgb(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)=
">;</span> <span style=3D"color:rgb(64,96,128)">}</span>
    <span style=3D"color:rgb(0,102,238)">std</span><span style=3D"color:rgb=
(64,96,128)">::</span>byte<span style=3D"color:rgb(48,128,128)">*</span> be=
gin<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(4=
8,128,128)">)</span>    <span style=3D"color:rgb(64,96,128)">{</span> <span=
 style=3D"color:rgb(32,0,128);font-weight:bold">return</span> func_table<sp=
an style=3D"color:rgb(48,128,128)">-</span><span style=3D"color:rgb(48,128,=
128)">&gt;</span>begin<span style=3D"color:rgb(48,128,128)">(</span><span s=
tyle=3D"color:rgb(32,0,128);font-weight:bold">this</span><span style=3D"col=
or:rgb(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span> <=
span style=3D"color:rgb(64,96,128)">}</span>
    <span style=3D"color:rgb(0,102,238)">std</span><span style=3D"color:rgb=
(64,96,128)">::</span>byte<span style=3D"color:rgb(48,128,128)">*</span> en=
d<span style=3D"color:rgb(48,128,128)">(</span><span style=3D"color:rgb(48,=
128,128)">)</span>      <span style=3D"color:rgb(64,96,128)">{</span> <span=
 style=3D"color:rgb(32,0,128);font-weight:bold">return</span> func_table<sp=
an style=3D"color:rgb(48,128,128)">-</span><span style=3D"color:rgb(48,128,=
128)">&gt;</span>end<span style=3D"color:rgb(48,128,128)">(</span><span sty=
le=3D"color:rgb(32,0,128);font-weight:bold">this</span><span style=3D"color=
:rgb(48,128,128)">)</span><span style=3D"color:rgb(64,96,128)">;</span> <sp=
an style=3D"color:rgb(64,96,128)">}</span>
<span style=3D"color:rgb(64,96,128)">}</span><span style=3D"color:rgb(64,96=
,128)">;</span>
</pre><p></p>
<ul><li><code>acquire()</code> increments the reference counter, and return=
s the previous value</li><li><code>release()</code> decrements the referenc=
e counter and, if it becames zero, deallocates the memory.</li><li><code>un=
ique()</code> tells whether the reretence countes is equal to one.</li><li>=
<code>begin()</code> and <code>end()</code> return the memory region that c=
ontains the string.</li><li><code>api_string_mem_base::abi_version</code> s=
hall be equall to zero.</li></ul></div>
</div>
</div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAF9gR9e5Kfy%2BTBtkRf-2i8EQ42Q5eRTQc0=
P9HLu9PP9UG4RCjg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9e5Kfy%2B=
TBtkRf-2i8EQ42Q5eRTQc0P9HLu9PP9UG4RCjg%40mail.gmail.com</a>.<br />

--000000000000d314f60578fc52dc--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 24 Oct 2018 16:27:43 -0700
Raw View
On Wednesday, 24 October 2018 09:53:07 PDT Roberto Hinz wrote:
> Almost every API contains some functions that receive or return strings.
> Yet, the C++ standard does not provide any good solution to transfer
> strings across modules boundaries. While raw strings and
> std::basic_string_view are not able to manage dynamic allocated memory,
> std::basic_string does not have a standard ABI and its header is expensive
> to compile.
>
> Is there any effort to address this going on?

I think the majority of people disagree that there is a problem in the first
place: std::basic_string is sufficient. ABI is not a problem that the standard
deals with and compilation times are a QoI issue.

So, no, there's no effort that I know of to act in this area.

PS: I maintain QString and I'm not going to drop it any time soon.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6761030.U8MmvgIJ5B%40tjmaciei-mobl1.

.


Author: Nevin Liber <nevin@eviloverlord.com>
Date: Thu, 25 Oct 2018 00:21:56 -0500
Raw View
--00000000000041daa6057906ca55
Content-Type: text/plain; charset="UTF-8"

On Wed, Oct 24, 2018 at 11:53 AM Roberto Hinz <robhz786@gmail.com> wrote:

> Almost every API contains some functions that receive or return strings.
> Yet, the C++ standard does not provide any good solution to transfer
> strings across modules boundaries. While raw strings and
> std::basic_string_view are not able to manage dynamic allocated memory,
> std::basic_string does not have a standard ABI and its header is
> expensive to compile.
>
If you are looking for a string whose individual characters can't be
modified, that kind of already exists as std::runtime_error.
--
 Nevin ":-)" Liber  <mailto:nevin@eviloverlord.com>  +1-847-691-1404

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGg_6%2BOJbVjX%3DMUyNhz-V8cJ_24nm6tq4yv0Fn%3D%2BACz5V%3DBMdg%40mail.gmail.com.

--00000000000041daa6057906ca55
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Wed, Oct 24, 2018 at 11:53 AM Roberto Hinz &lt;<a href=
=3D"mailto:robhz786@gmail.com">robhz786@gmail.com</a>&gt; wrote:<br><div cl=
ass=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0=
 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div st=
yle=3D"font-family:arial,helvetica,sans-serif"><div id=3D"m_-22097882498186=
01765m_4655701241357336627m_-203957810354332258gmail-preview1" class=3D"m_-=
2209788249818601765m_4655701241357336627m_-203957810354332258gmail-g-b m_-2=
209788249818601765m_4655701241357336627m_-203957810354332258gmail-g-b--t1of=
2 m_-2209788249818601765m_4655701241357336627m_-203957810354332258gmail-spl=
it m_-2209788249818601765m_4655701241357336627m_-203957810354332258gmail-sp=
lit-preview">
  <div id=3D"m_-2209788249818601765m_4655701241357336627m_-2039578103543322=
58gmail-preview" class=3D"m_-2209788249818601765m_4655701241357336627m_-203=
957810354332258gmail-preview-html"><p>Almost
 every API contains some functions that receive or return strings. Yet,=20
the C++ standard does not provide any good solution to transfer strings=20
across modules boundaries. While raw strings and <code>std::basic_string_vi=
ew</code> are not able to manage dynamic allocated memory, <code>std::basic=
_string</code> does not have a standard ABI and its header is expensive to =
compile.</p></div></div></div></div></blockquote><div>If you are looking fo=
r a string whose individual characters can&#39;t be modified, that kind of =
already exists as std::runtime_error.</div></div>-- <br><div dir=3D"ltr" cl=
ass=3D"gmail_signature" data-smartmail=3D"gmail_signature"><div dir=3D"ltr"=
><div><div dir=3D"ltr"><div>=C2=A0Nevin &quot;:-)&quot; Liber=C2=A0 &lt;mai=
lto:<a href=3D"mailto:nevin@eviloverlord.com" target=3D"_blank">nevin@evilo=
verlord.com</a>&gt; =C2=A0+1-847-691-1404</div></div></div></div></div></di=
v>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAGg_6%2BOJbVjX%3DMUyNhz-V8cJ_24nm6tq=
4yv0Fn%3D%2BACz5V%3DBMdg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Df=
ooter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGg_6%=
2BOJbVjX%3DMUyNhz-V8cJ_24nm6tq4yv0Fn%3D%2BACz5V%3DBMdg%40mail.gmail.com</a>=
..<br />

--00000000000041daa6057906ca55--

.


Author: Roberto Hinz <robhz786@gmail.com>
Date: Thu, 25 Oct 2018 10:38:25 -0300
Raw View
--000000000000539c6305790db860
Content-Type: text/plain; charset="UTF-8"

On Wed, Oct 24, 2018 at 8:27 PM Thiago Macieira <thiago@macieira.org> wrote:

> On Wednesday, 24 October 2018 09:53:07 PDT Roberto Hinz wrote:
> > Almost every API contains some functions that receive or return strings.
> > Yet, the C++ standard does not provide any good solution to transfer
> > strings across modules boundaries. While raw strings and
> > std::basic_string_view are not able to manage dynamic allocated memory,
> > std::basic_string does not have a standard ABI and its header is
> expensive
> > to compile.
> >
> > Is there any effort to address this going on?
>
> I think the majority of people disagree that there is a problem in the
> first
> place: std::basic_string is sufficient. ABI is not a problem that the
> standard
> deals with and compilation times are a QoI issue.
>

I don't think we can put the full responsibility on the QoI.
std::basic_string depends on char_traits, allocator, iterator_traits.
While api_string requires only on <cstddef>.
I made some basic compilation_benchmarks
<https://github.com/robhz786/api_string/tree/master/compilation_benchmarks>
I got the following compilation times:


api_string std::string
gcc 8.2 0.050 s 0.185 s
clang 7.0 0.070 s 0.280 s

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9fe2h0mbVOmu7rjoaG5Xrs2N8Jk4p_rdOcX6RYZN1VNJQ%40mail.gmail.com.

--000000000000539c6305790db860
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_quote"><div dir=3D"ltr">On Wed, Oc=
t 24, 2018 at 8:27 PM Thiago Macieira &lt;<a href=3D"mailto:thiago@macieira=
..org" target=3D"_blank">thiago@macieira.org</a>&gt; wrote:<br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex">On Wednesday, 24 October 2018 09:53:07 PDT Roberto =
Hinz wrote:<br>
&gt; Almost every API contains some functions that receive or return string=
s.<br>
&gt; Yet, the C++ standard does not provide any good solution to transfer<b=
r>
&gt; strings across modules boundaries. While raw strings and<br>
&gt; std::basic_string_view are not able to manage dynamic allocated memory=
,<br>
&gt; std::basic_string does not have a standard ABI and its header is expen=
sive<br>
&gt; to compile.<br>
&gt; <br>
&gt; Is there any effort to address this going on?<br>
<br>
I think the majority of people disagree that there is a problem in the firs=
t <br>
place: <span class=3D"gmail_default" style=3D"font-family:arial,helvetica,s=
ans-serif"></span>std::basic_string is sufficient. ABI is not a problem tha=
t the standard <br>
deals with and compilation times are a QoI issue.<br></blockquote><div><br>=
</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_=
default">I don&#39;t think we can put the full responsibility on the QoI.</=
div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_de=
fault"><span class=3D"gmail_default" style=3D"font-family:arial,helvetica,s=
ans-serif"></span>std::basic_string depends on char_traits, allocator, iter=
ator_traits.</div><div style=3D"font-family:arial,helvetica,sans-serif" cla=
ss=3D"gmail_default">While api_string requires only on &lt;cstddef&gt;.</di=
v><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_defa=
ult"></div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"g=
mail_default">I made some basic <a href=3D"https://github.com/robhz786/api_=
string/tree/master/compilation_benchmarks">compilation_benchmarks</a></div>=
</div><div class=3D"gmail_quote"><div style=3D"font-family:arial,helvetica,=
sans-serif" class=3D"gmail_default">I got the following compilation times:<=
/div><br><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gma=
il_default"><table width=3D"312" height=3D"73"><thead><tr><th><br></th>
<th align=3D"center">api_string</th>
<th align=3D"right">std::string</th>
</tr>
</thead>
<tbody>
<tr>
<td>gcc 8.2</td>
<td align=3D"center">0.050 s</td>
<td align=3D"right">0.185 s</td>
</tr>
<tr>
<td>clang 7.0</td>
<td align=3D"center">0.070 s</td>
<td align=3D"right">0.280 s</td></tr></tbody></table></div><div style=3D"fo=
nt-family:arial,helvetica,sans-serif" class=3D"gmail_default"><br></div><di=
v style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_default">=
<br></div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gm=
ail_default"><br></div><div style=3D"font-family:arial,helvetica,sans-serif=
" class=3D"gmail_default"><br></div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAF9gR9fe2h0mbVOmu7rjoaG5Xrs2N8Jk4p_r=
dOcX6RYZN1VNJQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9fe2h0mbVOm=
u7rjoaG5Xrs2N8Jk4p_rdOcX6RYZN1VNJQ%40mail.gmail.com</a>.<br />

--000000000000539c6305790db860--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 25 Oct 2018 21:39:21 -0700
Raw View
On Thursday, 25 October 2018 06:38:25 PDT Roberto Hinz wrote:
> I don't think we can put the full responsibility on the QoI.
> std::basic_string depends on char_traits, allocator, iterator_traits.
> While api_string requires only on <cstddef>.

Which is a problem. You're not going to get enough adoption without an
allocator template parameter. For example, I mentioned I maintain QString: I
would absolutely not be interested in your API unless it can be made to
deallocate using QArrayData.

I don't think you can get away from having an iterator either. But that does
not mean the header for iterator_traits needs to be included.

> I made some basic compilation_benchmarks
> <https://github.com/robhz786/api_string/tree/master/compilation_benchmarks>
> I got the following compilation times:
>
> api_string std::string
> gcc 8.2 0.050 s 0.185 s
> clang 7.0 0.070 s 0.280 s

Please also try libc++'s implementation of std::string.

But I don't see compilation time as an argument. It is most definitely QoI:
for example, a compiler can react to #include <string> by inserting a pre-
compiled implementation into the AST. I also don't think your prototype is
representative of what the final version's build time would be, and moreover
the cost is amortised by using proper precompiled headers anyway.

So, can you describe the benefits your API would have or problems it would
solve, without referring to build times and ABI?

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/13400688.pJn7XIzHAo%40tjmaciei-mobl1.

.


Author: Roberto Hinz <robhz786@gmail.com>
Date: Fri, 26 Oct 2018 13:41:02 -0300
Raw View
--000000000000404e0f05792463cf
Content-Type: text/plain; charset="UTF-8"

On Fri, Oct 26, 2018 at 1:39 AM Thiago Macieira <thiago@macieira.org> wrote:

> On Thursday, 25 October 2018 06:38:25 PDT Roberto Hinz wrote:
> > I don't think we can put the full responsibility on the QoI.
> > std::basic_string depends on char_traits, allocator, iterator_traits.
> > While api_string requires only on <cstddef>.
>
> Which is a problem. You're not going to get enough adoption without an
> allocator template parameter. For example, I mentioned I maintain QString:
> I
> would absolutely not be interested in your API unless it can be made to
> deallocate using QArrayData.
>

It's possible to implement a function that instantiates an api_string with
an
alternative allocator. But I would leave such function in a separate header.
A copy of allocator object would not be stored as member variable of
api_string, but inside the allocated memory, together with the reference
counters.


> I don't think you can get away from having an iterator either. But that
> does
> not mean the header for iterator_traits needs to be included.
>

api_string does support iterators. I just left reverse iterators out,
because they would require random_access_iterator_tag defined
in <iterator>. But iterator_traits seems indeed unnecessary.


> > I made some basic compilation_benchmarks
> > <
> https://github.com/robhz786/api_string/tree/master/compilation_benchmarks>
> > I got the following compilation times:
> >
> > api_string std::string
> > gcc 8.2 0.050 s 0.185 s
> > clang 7.0 0.070 s 0.280 s
>
> Please also try libc++'s implementation of std::string.
>

This test actually uses libc++ on clang, I forgot to mention


> But I don't see compilation time as an argument. It is most definitely
> QoI:
> for example, a compiler can react to #include <string> by inserting a pre-
> compiled implementation into the AST.


I think only a compiler implementer can tell us how feasible is that.
For example, how could a clang user switch from libc++ to libstdc++
if std::string is pre-compiled ? If they didn't solve the problem yet,
probably it's because it's not easy.

Certainly, there is a demand for it. Sometime ago in the boost list,
they were considering a breaking change in Boost.System by
replacing the return type of error_code::message() from std::string
to std::string_view just to reduce compilation times [1].
There is also a post on reddit complaining about it [2].

I also don't think your prototype is
> representative of what the final version's build time would be,
>

Yes, this is indeed a concern I have.


> So, can you describe the benefits your API would have or problems it would
> solve, without referring to build times and ABI?
>

1) Its copy constructor is always fast and never throws ( because it only
needs to increment the reference count ). This makes it ideal to be
stored inside exceptions

2) If you want to create a api_string from a raw string that has static
storage duration - like a string literal, which is very common - then you
can skip the memory allocation and copy, by using the api_string_ref()
function. This creates an api_string in "reference mode", that only
references the char array without ever deleting it.

In sum, I would say api_string aims to be ideal return string type.

Best regards,
Roberto

[1]
http://boost.2283326.n4.nabble.com/system-Would-it-be-possible-to-trial-a-breaking-change-to-Boost-System-and-see-what-happens-tt4701008.html
[2]
https://www.reddit.com/r/cpp/comments/83rf8o/stl_header_token_parsing_benchmarks_for_libstdc_5/

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9eYfBmL7rtc%2BuZ6L0q2jkQCPiJenwmfWGsDz4oBSx%2ByFw%40mail.gmail.com.

--000000000000404e0f05792463cf
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"><div dir=3D"ltr"><div class=3D"gmail_defa=
ult" style=3D"font-family:arial,helvetica,sans-serif"><br></div><br><div cl=
ass=3D"gmail_quote"><div dir=3D"ltr">On Fri, Oct 26, 2018 at 1:39 AM Thiago=
 Macieira &lt;<a href=3D"mailto:thiago@macieira.org" target=3D"_blank">thia=
go@macieira.org</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);pad=
ding-left:1ex">On Thursday, 25 October 2018 06:38:25 PDT Roberto Hinz wrote=
:<br>
&gt; I don&#39;t think we can put the full responsibility on the QoI.<br>
&gt; std::basic_string depends on char_traits, allocator, iterator_traits.<=
br>
&gt; While api_string requires only on &lt;cstddef&gt;.<br>
<br>
Which is a problem. You&#39;re not going to get enough adoption without an =
<br>
allocator template parameter. For example, I mentioned I maintain QString: =
I <br>
would absolutely not be interested in your API unless it can be made to <br=
>
deallocate using QArrayData.<br></blockquote><div><br></div><div style=3D"f=
ont-family:arial,helvetica,sans-serif" class=3D"gmail_default">It&#39;s pos=
sible to implement a function that instantiates an api_string with an</div>=
<div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_defaul=
t">alternative allocator. But I would leave such function in a separate hea=
der.</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gm=
ail_default">A copy of allocator object would not be stored as member varia=
ble of</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"=
gmail_default"> api_string, but inside the allocated memory, together with =
the reference</div><div style=3D"font-family:arial,helvetica,sans-serif" cl=
ass=3D"gmail_default"> counters. <br></div><div style=3D"font-family:arial,=
helvetica,sans-serif" class=3D"gmail_default"></div><div></div><div>=C2=A0<=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left:1px solid rgb(204,204,204);padding-left:1ex">
I don&#39;t think you can get away from having an iterator either. But that=
 does <br>
not mean the header for <span class=3D"gmail_default" style=3D"font-family:=
arial,helvetica,sans-serif"></span>iterator_traits needs to be included.<br=
></blockquote><div><div style=3D"font-family:arial,helvetica,sans-serif" cl=
ass=3D"gmail_default"><br></div><div style=3D"font-family:arial,helvetica,s=
ans-serif" class=3D"gmail_default"><div style=3D"font-family:arial,helvetic=
a,sans-serif" class=3D"gmail_default">api_string does support iterators. I =
just left reverse iterators out,</div><div style=3D"font-family:arial,helve=
tica,sans-serif" class=3D"gmail_default">because they would require <span c=
lass=3D"m_1052260934517180270gmail-mw-geshi m_1052260934517180270gmail-cpp =
m_1052260934517180270gmail-source-cpp">random_access_iterator_tag defined</=
span></div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"g=
mail_default"><span class=3D"m_1052260934517180270gmail-mw-geshi m_10522609=
34517180270gmail-cpp m_1052260934517180270gmail-source-cpp"> in &lt;iterato=
r&gt;. But <span class=3D"gmail_default" style=3D"font-family:arial,helveti=
ca,sans-serif"></span>iterator_traits seems indeed unnecessary.</span></div=
><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_defau=
lt"></div></div><div style=3D"font-family:arial,helvetica,sans-serif" class=
=3D"gmail_default"></div></div><div>=C2=A0<br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,=
204,204);padding-left:1ex">
&gt; I made some basic compilation_benchmarks<br>
&gt; &lt;<a href=3D"https://github.com/robhz786/api_string/tree/master/comp=
ilation_benchmarks" rel=3D"noreferrer" target=3D"_blank">https://github.com=
/robhz786/api_string/tree/master/compilation_benchmarks</a>&gt;<br>
&gt; I got the following compilation times:<br>
&gt; <br>
&gt; api_string std::string<br>
&gt; gcc 8.2 0.050 s 0.185 s<br>
&gt; clang 7.0 0.070 s 0.280 s<br>
<br>
Please also try libc++&#39;s implementation of std::string.<br></blockquote=
><div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_=
default"></div><div style=3D"font-family:arial,helvetica,sans-serif" class=
=3D"gmail_default"><br></div><div style=3D"font-family:arial,helvetica,sans=
-serif" class=3D"gmail_default">This test actually uses libc++ on clang, I =
forgot to mention<br></div></div><div></div><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid=
 rgb(204,204,204);padding-left:1ex">
But I don&#39;t see compilation time as an argument. It is most definitely =
QoI: <br>
for example, a compiler can react to #include &lt;string&gt; by inserting a=
 pre-<br>
compiled implementation into the AST. </blockquote><div><div style=3D"font-=
family:arial,helvetica,sans-serif" class=3D"gmail_default"></div><div style=
=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_default"><br></d=
iv><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_def=
ault">I think only a compiler implementer can tell us how feasible is that.=
</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_=
default">For example, how could a clang user switch from libc++ to libstdc+=
+</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail=
_default">if std::string is pre-compiled ? If they didn&#39;t solve the pro=
blem yet,</div><div style=3D"font-family:arial,helvetica,sans-serif" class=
=3D"gmail_default"> probably it&#39;s because it&#39;s not easy.</div><div =
style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_default"><b=
r></div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmai=
l_default">Certainly, there is a demand for it. Sometime ago in the boost l=
ist,</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gm=
ail_default">they were considering a breaking change in Boost.System by<br>=
</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_=
default">replacing the return type of error_code::message() from std::strin=
g</div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail=
_default"> to std::string_view just to reduce compilation times [1].<br></d=
iv><span class=3D"gmail_default" style=3D"font-family:arial,helvetica,sans-=
serif"></span><span class=3D"gmail_default" style=3D"font-family:arial,helv=
etica,sans-serif"></span>There is also a post on reddit complaining about i=
t [2]<span class=3D"gmail_default" style=3D"font-family:arial,helvetica,san=
s-serif">.</span><br></div><div><br></div><blockquote class=3D"gmail_quote"=
 style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);p=
adding-left:1ex">I also don&#39;t think your prototype is <br>
representative of what the final version&#39;s build time would be, <span c=
lass=3D"gmail_default" style=3D"font-family:arial,helvetica,sans-serif"></s=
pan><br></blockquote><div><div style=3D"font-family:arial,helvetica,sans-se=
rif" class=3D"gmail_default"></div><div style=3D"font-family:arial,helvetic=
a,sans-serif" class=3D"gmail_default"><br></div><div style=3D"font-family:a=
rial,helvetica,sans-serif" class=3D"gmail_default">Yes, this is indeed a co=
ncern I have.</div></div><div></div><div></div><div>=C2=A0<br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1p=
x solid rgb(204,204,204);padding-left:1ex">
So, can you describe the benefits your API would have or problems it would =
<br>
solve, without referring to build times and ABI?<br></blockquote><div></div=
><div><br></div><div><div style=3D"font-family:arial,helvetica,sans-serif" =
class=3D"gmail_default">1) Its copy constructor is always fast and never th=
rows <span class=3D"gmail_default" style=3D"font-family:arial,helvetica,san=
s-serif">( because it only</span></div></div><div><span class=3D"gmail_defa=
ult" style=3D"font-family:arial,helvetica,sans-serif">needs to increment th=
e reference count ). This makes it ideal to be</span></div><div><span class=
=3D"gmail_default" style=3D"font-family:arial,helvetica,sans-serif">stored =
inside exceptions</span></div><div><span class=3D"gmail_default" style=3D"f=
ont-family:arial,helvetica,sans-serif"></span><span class=3D"gmail_default"=
 style=3D"font-family:arial,helvetica,sans-serif"><br></span></div><div><sp=
an class=3D"gmail_default" style=3D"font-family:arial,helvetica,sans-serif"=
>2) If you want to create a api_string from a raw string that has static</s=
pan></div><div><span class=3D"gmail_default" style=3D"font-family:arial,hel=
vetica,sans-serif"> storage duration - like a string literal, which is very=
 common - then you<br></span></div><div><span class=3D"gmail_default" style=
=3D"font-family:arial,helvetica,sans-serif">can skip the memory allocation =
and copy, by using the api_string_ref()</span></div><div><span class=3D"gma=
il_default" style=3D"font-family:arial,helvetica,sans-serif"> function. Thi=
s creates an api_string in &quot;reference mode&quot;, that only</span></di=
v><div><span class=3D"gmail_default" style=3D"font-family:arial,helvetica,s=
ans-serif"> references the char array without ever deleting it.</span><br><=
/div><div><br></div><div><div style=3D"font-family:arial,helvetica,sans-ser=
if" class=3D"gmail_default">In sum, I would say api_string aims to be ideal=
 return string type.</div></div><div><br></div><div><div style=3D"font-fami=
ly:arial,helvetica,sans-serif" class=3D"gmail_default">Best regards,<div st=
yle=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_default">Robe=
rto</div><br></div></div><div><div style=3D"font-family:arial,helvetica,san=
s-serif" class=3D"gmail_default">[1]=C2=A0<a href=3D"http://boost.2283326.n=
4.nabble.com/system-Would-it-be-possible-to-trial-a-breaking-change-to-Boos=
t-System-and-see-what-happens-tt4701008.html" target=3D"_blank">http://boos=
t.2283326.n4.nabble.com/system-Would-it-be-possible-to-trial-a-breaking-cha=
nge-to-Boost-System-and-see-what-happens-tt4701008.html</a></div><div style=
=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_default">[2] <a =
href=3D"https://www.reddit.com/r/cpp/comments/83rf8o/stl_header_token_parsi=
ng_benchmarks_for_libstdc_5/" target=3D"_blank">https://www.reddit.com/r/cp=
p/comments/83rf8o/stl_header_token_parsing_benchmarks_for_libstdc_5/</a><br=
></div><br></div><div><br></div><div><br></div><div style=3D"font-family:ar=
ial,helvetica,sans-serif" class=3D"gmail_default"><br></div></div></div></d=
iv></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAF9gR9eYfBmL7rtc%2BuZ6L0q2jkQCPiJenw=
mfWGsDz4oBSx%2ByFw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9eYfBmL=
7rtc%2BuZ6L0q2jkQCPiJenwmfWGsDz4oBSx%2ByFw%40mail.gmail.com</a>.<br />

--000000000000404e0f05792463cf--

.


Author: pasa@lib.hu
Date: Fri, 26 Oct 2018 09:48:22 -0700 (PDT)
Raw View
------=_Part_993_110826378.1540572502751
Content-Type: multipart/alternative;
 boundary="----=_Part_994_1398337227.1540572502751"

------=_Part_994_1398337227.1540572502751
Content-Type: text/plain; charset="UTF-8"

By a pint I would say "we already have one abomination for a standard
string, do we really need more of them?" but let's skip over that, As I can
see worse things than to work with a suboptimal string type in an
application: that is to work with *multiple* string types.

It's problematic even in a library, say the standard. Did you read early
criticisms, like yey, C++ lib now have an actual string -- too bad the said
lib is not aware of it at all. fopen and a zillion other parts talk char
const*. Some of the more recent parts (filesystem?) might be ahead.  Now
suppose there was a general improvement and the library learned to talk
std::string. And your version gets in. Now all those functions should learn
std::astring too, maybe with all combinations.

Yeah, there are cute methods to deal with the mess (see Matthew Wilson's
shims, veneers and other adapters) but wise people just want to avoid the
mess in the first place. And that route is still a huge task.

I think that is one of the main reasons we're still stuck with the one
std::string despite it was not exactly liked from the boot and capital
mistakes discovered (not limited to originally aiming COW that was
forbidden).

IMHO if you presented a perfect magical thing that combined all the
benefits of all known designs (and we had many even pre-standard), it would
still be an uphill battle to get in. One that could be won with 'you can
just replace your std::string usage'.

And yours is not really impressive, and whoever wanted an immutable string,
instead of picking up one of the actually good full-featured ones just
wrote it, and is using it for decades.   While the compilation time
argument is very artificial, your diff stands up only in writing "hello
world" -- in any realistic application you start with including half of STL
and a ton of platform/framework headers. Plenty of those probably
precompiled. So there the difference will just disappear.  Or turn the
other way, considering the chances <string> already got included just
because some component supported it.

Meanwhile I fully support the suggestion others made: publish your string
as standalone library (maybe in boost, but outside is okay too). For those
who find it useful it will not lack the std:: prefix.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/bcf21167-2686-4647-80ca-ae92eeaf6115%40isocpp.org.

------=_Part_994_1398337227.1540572502751
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>By a pint I would say &quot;we already have one abomi=
nation for a standard string, do we really need more of them?&quot; but let=
&#39;s skip over that, As I can see worse things than to work with a subopt=
imal string type in an application: that is to work with *multiple* string =
types.</div><div><br></div><div>It&#39;s problematic even in a library, say=
 the standard. Did you read early criticisms, like yey, C++ lib now have an=
 actual string -- too bad the said lib is not aware of it at all. fopen and=
 a zillion other parts talk char const*. Some of the more recent parts (fil=
esystem?) might be ahead.=C2=A0 Now suppose there was a general improvement=
 and the library learned to talk std::string. And your version gets in. Now=
 all those functions should learn std::astring too, maybe with all combinat=
ions.</div><div><br></div><div>Yeah, there are cute methods to deal with th=
e mess (see Matthew Wilson&#39;s shims, veneers and other adapters) but wis=
e people just want to avoid the mess in the first place. And that route is =
still a huge task.</div><div><br></div><div>I think that is one of the main=
 reasons we&#39;re still stuck with the one std::string despite it was not =
exactly liked from the boot and capital mistakes discovered (not limited to=
 originally aiming COW that was forbidden).=C2=A0 <br></div><div><br></div>=
<div>IMHO if you presented a perfect magical thing that combined all the be=
nefits of all known designs (and we had many even pre-standard), it would s=
till be an uphill battle to get in. One that could be won with &#39;you can=
 just replace your std::string usage&#39;.</div><div><br></div><div>And you=
rs is not really impressive, and whoever wanted an immutable string, instea=
d of picking up one of the actually good full-featured ones just wrote it, =
and is using it for decades.=C2=A0=C2=A0 While the compilation time argumen=
t is very artificial, your diff stands up only in writing &quot;hello world=
&quot; -- in any realistic application you start with including half of STL=
 and a ton of platform/framework headers. Plenty of those probably precompi=
led. So there the difference will just disappear.=C2=A0 Or turn the other w=
ay, considering the chances &lt;string&gt; already got included just becaus=
e some component supported it.</div><div><br></div>Meanwhile I fully suppor=
t the suggestion others made: publish your string as standalone library (ma=
ybe in boost, but outside is okay too). For those who find it useful it wil=
l not lack the std:: prefix. <br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/bcf21167-2686-4647-80ca-ae92eeaf6115%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/bcf21167-2686-4647-80ca-ae92eeaf6115=
%40isocpp.org</a>.<br />

------=_Part_994_1398337227.1540572502751--

------=_Part_993_110826378.1540572502751--

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 26 Oct 2018 10:59:05 -0700
Raw View
On Friday, 26 October 2018 09:41:02 PDT Roberto Hinz wrote:
> It's possible to implement a function that instantiates an api_string with
> an
> alternative allocator. But I would leave such function in a separate header.
> A copy of allocator object would not be stored as member variable of
> api_string, but inside the allocated memory, together with the reference
> counters.

So you need an extra memory allocation to use this class? Please account for
that when discussing the benefits and disadvantages of your API.

> > But I don't see compilation time as an argument. It is most definitely
> > QoI:
> > for example, a compiler can react to #include <string> by inserting a pre-
> > compiled implementation into the AST.
>
> I think only a compiler implementer can tell us how feasible is that.
> For example, how could a clang user switch from libc++ to libstdc++
> if std::string is pre-compiled ? If they didn't solve the problem yet,
> probably it's because it's not easy.

They didn't implement it because they didn't want it. The switch you mentioned
is part of their objectives, as is the decoupling between the compiler and the
standard library. Implementing a non-file #include mechanism would go against
that.

What I am saying is that a compiler could choose to do that, under different
circumstances.

> > So, can you describe the benefits your API would have or problems it would
> > solve, without referring to build times and ABI?
>
> 1) Its copy constructor is always fast and never throws ( because it only
> needs to increment the reference count ). This makes it ideal to be
> stored inside exceptions

I personally like it this way. As you may be aware, QString is reference-
counted, as are most Qt container types.

But I am definitely not in the majority. The view of the majority of committee
members and others in this list is that reference counting is bad, especially
if (or is it "only if"?) it's coupled with Copy-on-Write.

> 2) If you want to create a api_string from a raw string that has static
> storage duration - like a string literal, which is very common - then you
> can skip the memory allocation and copy, by using the api_string_ref()
> function. This creates an api_string in "reference mode", that only
> references the char array without ever deleting it.

QString has that too, called fromRawData(), which allocates a memory block for
the refcount and tracks that, but doesn't own the character data itself.

I'm changing it for Qt 6: instead, if the control block pointer is null,
there's no reference counting needed. This could lead to further code merges
between QString and QStringView, though prototypes need to be written still.

> In sum, I would say api_string aims to be ideal return string type.

It's worse than std::string_view, which has a trivial copy constructor. But it
does support returning an allocated string and passing on its lifetime, which
std::string_view can't do.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center



--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2314717.GH8Ag49nql%40tjmaciei-mobl1.

.


Author: Roberto Hinz <robhz786@gmail.com>
Date: Fri, 26 Oct 2018 16:25:51 -0300
Raw View
--000000000000b35194057926b0d3
Content-Type: text/plain; charset="UTF-8"

On Fri, Oct 26, 2018 at 1:48 PM <pasa@lib.hu> wrote:

> By a pint I would say "we already have one abomination for a standard
> string, do we really need more of them?" but let's skip over that, As I can
> see worse things than to work with a suboptimal string type in an
> application: that is to work with *multiple* string types.
>
> It's problematic even in a library, say the standard. Did you read early
> criticisms, like yey, C++ lib now have an actual string -- too bad the said
> lib is not aware of it at all. fopen and a zillion other parts talk char
> const*. Some of the more recent parts (filesystem?) might be ahead.  Now
> suppose there was a general improvement and the library learned to talk
> std::string. And your version gets in. Now all those functions should learn
> std::astring too, maybe with all combinations.
>
>
We could make std::string convertible from and to api_string. It is
possible to implement std::string so that it uses the same internal data
structure of api_string. This way, converting a std::string&& to api_string
would not require copy nor memory allocation: the content would just be
moved. The same optimization could be used to construct an std::string from
api_string&&, when the reference count is equal to one. ( Note: this does
not imply to use CoW on std::string ). Actually this is the other thing
that was about to propose. And there is a prototype in the repository.


And yours is not really impressive, and whoever wanted an immutable string,
> instead of picking up one of the actually good full-featured ones just
> wrote it, and is using it for decades.   While the compilation time
> argument is very artificial, your diff stands up only in writing "hello
> world" -- in any realistic application you start with including half of STL
> and a ton of platform/framework headers. Plenty of those probably
> precompiled. So there the difference will just disappear.  Or turn the
> other way, considering the chances <string> already got included just
> because some component supported it.
>
> Meanwhile I fully support the suggestion others made: publish your string
> as standalone library (maybe in boost, but outside is okay too). For those
> who find it useful it will not lack the std:: prefix.
>

I agree that there is nothing impressive in my string. The reason why I
proposed it directly here is that in order to be good api_string should be
well interoperable with std::string. So std::string would need to be
changed too, and also std::string_view.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9cm9vj8_RThm5eMhOjZXhuLEqOJxN83ed3sR1%2Bfqip%3DhA%40mail.gmail.com.

--000000000000b35194057926b0d3
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div dir=3D"ltr"><div dir=3D"ltr"><div class=3D"gmail_defa=
ult" style=3D"font-family:arial,helvetica,sans-serif"></div><br><div class=
=3D"gmail_quote"><div dir=3D"ltr">On Fri, Oct 26, 2018 at 1:48 PM &lt;<a hr=
ef=3D"mailto:pasa@lib.hu" target=3D"_blank">pasa@lib.hu</a>&gt; wrote:<br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><di=
v>By a pint I would say &quot;we already have one abomination for a standar=
d string, do we really need more of them?&quot; but let&#39;s skip over tha=
t, As I can see worse things than to work with a suboptimal string type in =
an application: that is to work with *multiple* string types.</div><div><br=
></div><div>It&#39;s problematic even in a library, say the standard. Did y=
ou read early criticisms, like yey, C++ lib now have an actual string -- to=
o bad the said lib is not aware of it at all. fopen and a zillion other par=
ts talk char const*. Some of the more recent parts (filesystem?) might be a=
head.=C2=A0 Now suppose there was a general improvement and the library lea=
rned to talk std::string. And your version gets in. Now all those functions=
 should learn std::astring too, maybe with all combinations.</div><div><br>=
</div></div></blockquote><div><br></div><div><div style=3D"font-family:aria=
l,helvetica,sans-serif" class=3D"gmail_default">We could make std::string c=
onvertible from and to api_string. It is possible to implement std::string =
so that it uses the same internal data structure of api_string. This way, c=
onverting a std::string&amp;&amp; to api_string would not require copy nor =
memory allocation: the content would just be moved. The same optimization c=
ould be used to construct an std::string from api_string&amp;&amp;, when th=
e reference count is equal to one. ( Note: this does not imply to use CoW o=
n std::string ). Actually this is the other thing that was about to propose=
.. And there is a prototype in the repository.</div><div><br></div></div><br=
><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border=
-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div></=
div><div>And yours is not really impressive, and whoever wanted an immutabl=
e string, instead of picking up one of the actually good full-featured ones=
 just wrote it, and is using it for decades.=C2=A0=C2=A0 While the compilat=
ion time argument is very artificial, your diff stands up only in writing &=
quot;hello world&quot; -- in any realistic application you start with inclu=
ding half of STL and a ton of platform/framework headers. Plenty of those p=
robably precompiled. So there the difference will just disappear.=C2=A0 Or =
turn the other way, considering the chances &lt;string&gt; already got incl=
uded just because some component supported it.</div><div><br></div>Meanwhil=
e I fully support the suggestion others made: publish your string as standa=
lone library (maybe in boost, but outside is okay too). For those who find =
it useful it will not lack the std:: prefix. <br></div></blockquote><div><b=
r></div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmai=
l_default">I agree that there is nothing impressive in my string. The reaso=
n why I proposed it directly here is that in order to be good api_string sh=
ould be well interoperable with std::string. So std::string would need to b=
e changed too, and also std::string_view.<br>=C2=A0<br></div><div style=3D"=
font-family:arial,helvetica,sans-serif" class=3D"gmail_default"><br></div><=
div style=3D"font-family:arial,helvetica,sans-serif" class=3D"gmail_default=
"><br></div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"=
gmail_default"></div></div></div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAF9gR9cm9vj8_RThm5eMhOjZXhuLEqOJxN83=
ed3sR1%2Bfqip%3DhA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9cm9vj8=
_RThm5eMhOjZXhuLEqOJxN83ed3sR1%2Bfqip%3DhA%40mail.gmail.com</a>.<br />

--000000000000b35194057926b0d3--

.


Author: Bjorn Reese <breese@mail1.stofanet.dk>
Date: Fri, 26 Oct 2018 23:04:47 +0200
Raw View
On 10/26/18 6:41 PM, Roberto Hinz wrote:

> Certainly, there is a demand for it. Sometime ago in the boost list,
> they were considering a breaking change in Boost.System by
> replacing the return type of error_code::message() from std::string
> to std::string_view just to reduce compilation times [1].
> There is also a post on reddit complaining about it [2].

That breaking change was not accepted into Boost.System. Instead a
backwardscompatible solution was chosen:

   https://pdimov.github.io/cpp-papers/P1197R0.html

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2353162d-d737-8140-6339-030a0a8670a8%40mail1.stofanet.dk.

.


Author: Roberto Hinz <robhz786@gmail.com>
Date: Fri, 26 Oct 2018 19:08:47 -0300
Raw View
--00000000000073b947057928f72e
Content-Type: text/plain; charset="UTF-8"

On Fri, Oct 26, 2018 at 2:59 PM Thiago Macieira <thiago@macieira.org> wrote:

> On Friday, 26 October 2018 09:41:02 PDT Roberto Hinz wrote:
> > It's possible to implement a function that instantiates an api_string
> with
> > an
> > alternative allocator. But I would leave such function in a separate
> header.
> > A copy of allocator object would not be stored as member variable of
> > api_string, but inside the allocated memory, together with the reference
> > counters.
>
> So you need an extra memory allocation to use this class? Please account
> for
> that when discussing the benefits and disadvantages of your API.
>

No, only one allocation. The counter, the allocator object and the
char array are all stored in the same allocated memory chunk.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9fu-gjuRKHA6N_SbLnn9Xo3KZ9ZM2Uz7pqx%2B3rELC%2BV9w%40mail.gmail.com.

--00000000000073b947057928f72e
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_default" style=3D"font-family:arial,he=
lvetica,sans-serif"><br></div><br><div class=3D"gmail_quote"><div dir=3D"lt=
r">On Fri, Oct 26, 2018 at 2:59 PM Thiago Macieira &lt;<a href=3D"mailto:th=
iago@macieira.org" target=3D"_blank">thiago@macieira.org</a>&gt; wrote:<br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex">On Friday, 26 October 2018 09:41:02 PD=
T Roberto Hinz wrote:<br>
&gt; It&#39;s possible to implement a function that instantiates an api_str=
ing with<br>
&gt; an<br>
&gt; alternative allocator. But I would leave such function in a separate h=
eader.<br>
&gt; A copy of allocator object would not be stored as member variable of<b=
r>
&gt; api_string, but inside the allocated memory, together with the referen=
ce<br>
&gt; counters.<br>
<br>
So you need an extra memory allocation to use this class? Please account fo=
r <br>
that when discussing the benefits and disadvantages of your API.<br></block=
quote><div><div style=3D"font-family:arial,helvetica,sans-serif" class=3D"g=
mail_default"></div><div style=3D"font-family:arial,helvetica,sans-serif" c=
lass=3D"gmail_default"><br></div><div style=3D"font-family:arial,helvetica,=
sans-serif" class=3D"gmail_default">No, only one allocation. The counter, t=
he allocator object and the</div><div style=3D"font-family:arial,helvetica,=
sans-serif" class=3D"gmail_default">char array are all stored in the same a=
llocated memory chunk.<br></div></div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAF9gR9fu-gjuRKHA6N_SbLnn9Xo3KZ9ZM2Uz=
7pqx%2B3rELC%2BV9w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAF9gR9fu-gju=
RKHA6N_SbLnn9Xo3KZ9ZM2Uz7pqx%2B3rELC%2BV9w%40mail.gmail.com</a>.<br />

--00000000000073b947057928f72e--

.