Discussion:
[std-proposals] a string type for APIs
Roberto Hinz
2018-10-24 16:53:07 UTC
Permalink
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Thiago Macieira
2018-10-24 23:27:43 UTC
Permalink
Post by Roberto Hinz
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Roberto Hinz
2018-10-25 13:38:25 UTC
Permalink
Post by Roberto Hinz
Post by Roberto Hinz
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
Post by Roberto Hinz
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Thiago Macieira
2018-10-26 04:39:21 UTC
Permalink
Post by Roberto Hinz
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.
Post by Roberto Hinz
I made some basic compilation_benchmarks
<https://github.com/robhz786/api_string/tree/master/compilation_benchmarks>
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Roberto Hinz
2018-10-26 16:41:02 UTC
Permalink
Post by Thiago Macieira
Post by Roberto Hinz
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.
Post by Thiago Macieira
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.
Post by Thiago Macieira
Post by Roberto Hinz
I made some basic compilation_benchmarks
<
https://github.com/robhz786/api_string/tree/master/compilation_benchmarks>
Post by Roberto Hinz
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
Post by Thiago Macieira
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
Post by Thiago Macieira
representative of what the final version's build time would be,
Yes, this is indeed a concern I have.
Post by Thiago Macieira
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Thiago Macieira
2018-10-26 17:59:05 UTC
Permalink
Post by Roberto Hinz
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.
Post by Roberto Hinz
Post by Thiago Macieira
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.
Post by Roberto Hinz
Post by Thiago Macieira
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.
Post by Roberto Hinz
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.
Post by Roberto Hinz
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Roberto Hinz
2018-10-26 22:08:47 UTC
Permalink
Post by Roberto Hinz
Post by Roberto Hinz
It's possible to implement a function that instantiates an api_string
with
Post by Roberto Hinz
an
alternative allocator. But I would leave such function in a separate
header.
Post by Roberto Hinz
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Bjorn Reese
2018-10-26 21:04:47 UTC
Permalink
Post by Roberto Hinz
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Nevin Liber
2018-10-25 05:21:56 UTC
Permalink
Post by Roberto Hinz
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:***@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+***@isocpp.org.
To post to this group, send email to std-***@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.
p***@lib.hu
2018-10-26 16:48:22 UTC
Permalink
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Roberto Hinz
2018-10-26 19:25:51 UTC
Permalink
Post by p***@lib.hu
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,
Post by p***@lib.hu
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+***@isocpp.org.
To post to this group, send email to std-***@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.
Loading...