Re: [Boost-users] [review][fixed_string] FixedString review starts today

classic Classic list List threaded Threaded
45 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
Zach Laine wrote:

> Throwing when the capacity would be exceeded is wrong.

No, it's not. It's correct. It's a runtime error, not a programming time
error.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
On Wed, Nov 27, 2019 at 11:01 AM Peter Dimov via Boost <
[hidden email]> wrote:

> Zach Laine wrote:
>
> > Throwing when the capacity would be exceeded is wrong.
>
> No, it's not. It's correct. It's a runtime error, not a programming time
> error.
>

Then why doesn't vector::operator[] throw?  In either case, you know what
the precondition is, and how to check it.  That's what makes this a user
error.  With out-of-memory, I have no way to programmatically check that
(within the standard).

Zach

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
Zach Laine wrote:

> On Wed, Nov 27, 2019 at 11:01 AM Peter Dimov via Boost
> <[hidden email]> wrote:
> > Zach Laine wrote:
> >
> > > Throwing when the capacity would be exceeded is wrong.
> >
> > No, it's not. It's correct. It's a runtime error, not a programming time
> > error.
>
> Then why doesn't vector::operator[] throw?  In either case, you know what
> the precondition is, and how to check it.  That's what makes this a user
> error.

What makes op[] a user error is that the index rarely comes from external
input. It typically comes from a variable that the programmer controls and
program logic ensures is in range.

Whereas when you += strings into a fixed capacity buffer, those are only
occasionally programmer-supplied. Program logic is not violated if the input
strings exceed the buffer.

Or stated differently, if in 90% of the cases the correct use of a function
would involve the programmer writing out the exact same

    if( !precondition ) throw exception();

thing that the function would have done itself were it throwing, the
function should be throwing.

Whereas when you do `for( int i = 0; i < n; ++i ) { something with v[i]; }`,
you don't need to insert the above before each [].


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
On Wed, Nov 27, 2019 at 11:23 AM Peter Dimov <[hidden email]> wrote:

> Zach Laine wrote:
> > On Wed, Nov 27, 2019 at 11:01 AM Peter Dimov via Boost
> > <[hidden email]> wrote:
> > > Zach Laine wrote:
> > >
> > > > Throwing when the capacity would be exceeded is wrong.
> > >
> > > No, it's not. It's correct. It's a runtime error, not a programming
> time
> > > error.
> >
> > Then why doesn't vector::operator[] throw?  In either case, you know
> what
> > the precondition is, and how to check it.  That's what makes this a user
> > error.
>
> What makes op[] a user error is that the index rarely comes from external
> input. It typically comes from a variable that the programmer controls and
> program logic ensures is in range.
>

I disagree.  What puts vector::operator+ inherently (which is directly
analogous to fixed_string::operator+) more out of programmer control than
vector::operator[]?

Moreover, there are two things to consider:

1) Can I use this function within a context in which I know that the
precondition check/throwing condition is not needed?

This is in part an efficiency concern, of course.  If I can check the
condition myself, outside of the function, I can write code that maintains
the invariant that the precondition is always true, or in which the
precondition is true within some limited scope.  I can then call the
function within that invariant-maintaining code or scope, and elide the
branches of the check.

2) If the check is needed, can the programmer write code that can sensibly
deal with the problem?

When I'm out of memory, I *may* be able to do something about that,
depending on my system.  For instance, running out of memory on a game
console is not an unusual thing, and I'll have a failover strategy for
that.  Running out of array-based storage is not as easily recoverable.

Unless the answers are 1) no and 2) yes, the function should not throw.

Whereas when you += strings into a fixed capacity buffer, those are only
> occasionally programmer-supplied. Program logic is not violated if the
> input
> strings exceed the buffer.
>

Ok, then do you advocate that fixed_string::operator+=(fixed_string) have
preconditions and not throw, and that fixed_string::operator+=(char const
*) should throw instead?  Only the latter could have come from an
end-user.  End users have no way of supplying fixed_strings to your program.


> Or stated differently, if in 90% of the cases the correct use of a
> function
> would involve the programmer writing out the exact same
>
>     if( !precondition ) throw exception();
>
> thing that the function would have done itself were it throwing, the
> function should be throwing.
>

I can get behind that.  I just don't think that I'd need to check-and-throw
everywhere that I would use fixed_string::operator+=.


> Whereas when you do `for( int i = 0; i < n; ++i ) { something with v[i];
> }`,
> you don't need to insert the above before each [].
>

On this we agree.

Zach

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
Zach Laine wrote:
> > What makes op[] a user error is that the index rarely comes from
> > external input. It typically comes from a variable that the programmer
> > controls and program logic ensures is in range.
>
> I disagree.  What puts vector::operator+ inherently (which is directly
> analogous to fixed_string::operator+) more out of programmer control than
> vector::operator[]?

Nothing inherently makes it so. It just is, in the observable universe.

> Moreover, there are two things to consider:
>
> 1) Can I use this function within a context in which I know that the
> precondition check/throwing condition is not needed?
>
> This is in part an efficiency concern, of course.

Even if this only occurs 0.1% of the time, the design should cater to it
because of the mere possibility?

The flip side is the loss of efficiency when you do have to check. You need
to compute the size of the argument twice, which in the char const* case
isn't free.

> 2) If the check is needed, can the programmer write code that can sensibly
> deal with the problem?

Sure, throw an exception. :-)

> Ok, then do you advocate that fixed_string::operator+=(fixed_string) have
> preconditions and not throw, and that fixed_string::operator+=(char const
> *) should throw instead?

No. I would "precondition" `op+=( char const (&)[ M ] )` (and op=) by
failing at compile time when M > N, because the size is known, but in
fixed_string's case, the size isn't known.

There's no significant difference between accumulating the elements of
vector<string> and those of vector<fixed_string> into a fixed_string. In
both cases, we have no idea whether they'll fit or not. And yes, when they
are known in advance, we can compute the final size in one loop, check, then
+= in a second loop, avoiding the check on each iteration. So there's a
potential efficiency loss here, outweighed by gain of convenience and loss
of buffer overflow exploits in the more common case where the accumulated
strings come one by one from input.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> I would "precondition" `op+=( char const (&)[ M ] )` (and op=) by failing
> at compile time when M > N, because the size is known, but in
> fixed_string's case, the size isn't known.

No I wouldn't. :-) The size isn't known in this case either. It's better to
diagnose_if the whole thing.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On Thu, Nov 28, 2019 at 9:52 AM Peter Dimov via Boost <[hidden email]>
wrote:

> Zach Laine wrote:
> > > What makes op[] a user error is that the index rarely comes from
> > > external input. It typically comes from a variable that the programmer
> > > controls and program logic ensures is in range.
> >
> > I disagree.  What puts vector::operator+ inherently (which is directly
> > analogous to fixed_string::operator+) more out of programmer control
> than
> > vector::operator[]?
>
> Nothing inherently makes it so. It just is, in the observable universe.
>
> > Moreover, there are two things to consider:
> >
> > 1) Can I use this function within a context in which I know that the
> > precondition check/throwing condition is not needed?
> >
> > This is in part an efficiency concern, of course.
>
> Even if this only occurs 0.1% of the time, the design should cater to it
> because of the mere possibility?
>
> The flip side is the loss of efficiency when you do have to check. You
> need
> to compute the size of the argument twice, which in the char const* case
> isn't free.
>
> > 2) If the check is needed, can the programmer write code that can
> sensibly
> > deal with the problem?
>
> Sure, throw an exception. :-)
>
> > Ok, then do you advocate that fixed_string::operator+=(fixed_string)
> have
> > preconditions and not throw, and that fixed_string::operator+=(char
> const
> > *) should throw instead?
>
> No. I would "precondition" `op+=( char const (&)[ M ] )` (and op=) by
> failing at compile time when M > N, because the size is known, but in
> fixed_string's case, the size isn't known.
>
> There's no significant difference between accumulating the elements of
> vector<string> and those of vector<fixed_string> into a fixed_string. In
> both cases, we have no idea whether they'll fit or not. And yes, when they
> are known in advance, we can compute the final size in one loop, check,
> then
> += in a second loop, avoiding the check on each iteration. So there's a
> potential efficiency loss here, outweighed by gain of convenience and loss
> of buffer overflow exploits in the more common case where the accumulated
> strings come one by one from input.
>

Ok, I understand your point a bit better now I think.  Is it the
unboundedly-large nature of a NTBS that has you concerned?  That is, do you
think that op+=(char) should assert and op+=(char const *) should throw?
That position makes sense to me, thought I don't share it -- though I think
that's just taste.  However, I cannot imagine why I'd ever want op+=(char)
or op+=(string_view) to throw.

Zach

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
On 2019-11-29 01:44, Zach Laine via Boost wrote:
>
> Ok, I understand your point a bit better now I think.  Is it the
> unboundedly-large nature of a NTBS that has you concerned?  That is, do you
> think that op+=(char) should assert and op+=(char const *) should throw?
> That position makes sense to me, thought I don't share it -- though I think
> that's just taste.  However, I cannot imagine why I'd ever want op+=(char)
> or op+=(string_view) to throw.

IIRC, append/insert/push_back will throw with any container or
std::string, if the result exceeds max_size(). It is only natural if
fixed_string does the same, it is the expected behavior.

You can argue for a separate set of unsafe insert methods that don't
perform the check and exhibit undefined behavior if the resulting length
exceeds the limit. But it should be very clear that the user must ensure
himself that it doesn't happen.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Zach Laine wrote:

> Ok, I understand your point a bit better now I think.  Is it the
> unboundedly-large nature of a NTBS that has you concerned?  That is, do
> you think that op+=(char) should assert and op+=(char const *) should
> throw?

No, I prefer all of them consistently throwing, even when the check is O(1).
My primary concern is not the loss of efficiency due to double checking,
it's to avoid buffer overflow exploits.

Yes, this will be less efficient if you += characters (but not by so much as
one might think), and yes, you can write code that will be correct if op+=
doesn't check. (Since operating on chars destroys optimizations due to
aliasing, the inner loop improves from

.L5:
        add     rax, 1
        movzx   ecx, BYTE PTR [rdx]
        cmp     rax, 511
        ja      .L11
        add     rdx, 1
        mov     QWORD PTR [rdi], rax
        mov     BYTE PTR [rdi+7+rax], cl
        cmp     rsi, rdx
        jne     .L5

https://godbolt.org/z/Z37Pmx

to

.L3:
        movzx   ecx, BYTE PTR [rdx+rax]
        add     rax, 1
        mov     QWORD PTR [rdi], rax
        mov     BYTE PTR [rdi+7+rax], cl
        cmp     r8, rax
        jne     .L3

https://godbolt.org/z/CXHRKQ

which is better, but far from optimal.)

I were implementing this class, I would always check in op+= (and append
etc) even if the specification says "Expects" instead of "Throws", I'd just
__builtin_trap instead of throwing. Otherwise, this is strcat all over
again, and there's a reason there was a big concerted push against this
style in/by Microsoft and elsewhere.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
I guess, this is a matter of design choice: do we want a `resize()` beyond
`capacity()` to be treated as a programmer bug (something that the library
does not offer) or a correct -- even if very occasional -- usage. Both have
their justification and both bring value; but making either choice renders
a different library, even if similar on the face value. The model with
throwing exceptions is the "infinite memory model": programmer can assume
that capacity is infinite and accept that at some point an exception will
remind her that the assumption could no longer be maintained. The UB model
makes the capacity part of the contract, and programmer takes
responsibility of maintaining it.

If all STL containers take the exception model, and this library aims at
being a drop-in replacement for std::string, the it would sound more
reasonable to adapt the "infinite capacity" model.

On the other hand, if the goal is to provide a container suitable for
embedded operations, where you cannot afford throwing exceptions the same
way as you cannot afford heap allocation, one would expect the other model.
This is what static_vector has chosen.

It looks to me that these two design goals cannot be pursued together:
* be a drop-in replacement for std::string
* be a tool for embedded systems (where resource/constraint awareness
changes the way one organize programs)

As they necessitate opposite design trade-offs. Authors of fixed_string
should make the call which goal they want to pursue and document it. And
from this choice the design trade-offs will follow.

static_string came from Beast. My guess is that Beast needs the "infinite
memory" model. If you are doing networking, you can afford occasional
memory allocation required by exceptions. And you want to favor buffer
overflow protection over bleeding edge performance.

This also justifies using different prefix ("fixed_") than in
static_vector, as the latter library chose a different model.

Regards,
&rzej;

pt., 29 lis 2019 o 01:18 Andrey Semashev via Boost <[hidden email]>
napisał(a):

> On 2019-11-29 01:44, Zach Laine via Boost wrote:
> >
> > Ok, I understand your point a bit better now I think.  Is it the
> > unboundedly-large nature of a NTBS that has you concerned?  That is, do
> you
> > think that op+=(char) should assert and op+=(char const *) should throw?
> > That position makes sense to me, thought I don't share it -- though I
> think
> > that's just taste.  However, I cannot imagine why I'd ever want
> op+=(char)
> > or op+=(string_view) to throw.
>
> IIRC, append/insert/push_back will throw with any container or
> std::string, if the result exceeds max_size(). It is only natural if
> fixed_string does the same, it is the expected behavior.
>
> You can argue for a separate set of unsafe insert methods that don't
> perform the check and exhibit undefined behavior if the resulting length
> exceeds the limit. But it should be very clear that the user must ensure
> himself that it doesn't happen.
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> https://godbolt.org/z/Z37Pmx
> https://godbolt.org/z/CXHRKQ

I forgot to maintain a 0 terminator in this sketch; it's even worse with it.

.L5:
        add     rax, 1
        movzx   ecx, BYTE PTR [rdx]
        cmp     rax, 512
        ja      .L11
        add     rdx, 1
        mov     BYTE PTR [rdi+7+rax], cl
        mov     BYTE PTR [rdi+8+rax], 0
        mov     QWORD PTR [rdi], rax
        cmp     rsi, rdx
        jne     .L5

https://godbolt.org/z/nhYZQY

.L3:
        movzx   ecx, BYTE PTR [rdx+rax]
        mov     BYTE PTR [rdi+8+rax], cl
        add     rax, 1
        mov     BYTE PTR [rdi+8+rax], 0
        mov     QWORD PTR [rdi], rax
        cmp     r8, rax
        jne     .L3

https://godbolt.org/z/pGJRWs


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Andrzej Krzemienski wrote:

> On the other hand, if the goal is to provide a container suitable for
> embedded operations, where you cannot afford throwing exceptions the same
> way as you cannot afford heap allocation, one would expect the other
> model.

On embedded, you compile with -fno-exceptions and add

namespace boost
{
    void throw_exception( std::exception const& ) { __builtin_trap(); }
}

There's no need to afford exceptions, you just need to be able to afford the
potential loss in performance, basically one branch per append if not
heroically optimized away.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> and yes, you can write code that will be correct if op+= doesn't check.

Maybe you can, but I apparently can't. This is what I just wrote:

void my_append( fixed_string<512> & s, std::string_view s1, std::string_view
s2 )
{
    if( s.size() + s1.size() + s2.size() > s.max_size() ) throw
std::length_error( "" );

    s += s1;
    s += s2;
}

Is this correct? (Spoiler: no.)


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
I suspect (I am not programming in an embedded system) that rather than
relying on __builtin_trap() or std::abort(), what you do is start treating
a `resize()` over `capacity()` as a precondition violation (a bug). And
this causes a different programming model and the organization of your code.

Regards,
&rzej;

pt., 29 lis 2019 o 09:06 Peter Dimov via Boost <[hidden email]>
napisał(a):

> Andrzej Krzemienski wrote:
>
> > On the other hand, if the goal is to provide a container suitable for
> > embedded operations, where you cannot afford throwing exceptions the
> same
> > way as you cannot afford heap allocation, one would expect the other
> > model.
>
> On embedded, you compile with -fno-exceptions and add
>
> namespace boost
> {
>     void throw_exception( std::exception const& ) { __builtin_trap(); }
> }
>
> There's no need to afford exceptions, you just need to be able to afford
> the
> potential loss in performance, basically one branch per append if not
> heroically optimized away.
>
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 2019-11-29 11:12, Peter Dimov via Boost wrote:

>> and yes, you can write code that will be correct if op+= doesn't check.
>
> Maybe you can, but I apparently can't. This is what I just wrote:
>
> void my_append( fixed_string<512> & s, std::string_view s1,
> std::string_view s2 )
> {
>     if( s.size() + s1.size() + s2.size() > s.max_size() ) throw
> std::length_error( "" );
>
>     s += s1;
>     s += s2;
> }
>
> Is this correct? (Spoiler: no.)

I think, appending N strings still requires N tests, unless you know
that the string sizes combined don't overflow.

   size_t size_left = s.max_size() - s.size();
   if (s1.size() > size_left) throw_length_error();
   size_left -= s1.size();
   if (s2.size() > size_left) throw_length_error();

Or use unsigned __int128 to calculate the combined size. Alas, it's not
universally available.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Andrzej Krzemienski wrote:

> I suspect (I am not programming in an embedded system) that rather than
> relying on __builtin_trap() or std::abort(), what you do is start treating
> a `resize()` over `capacity()` as a precondition violation (a bug). And
> this causes a different programming model and the organization of your
> code.

That was exactly why I wrote

> > There's no need to afford exceptions, you just need to be able to afford
> > the potential loss in performance, basically one branch per append if
> > not heroically optimized away.

That is: in order to use the library as presented, you don't need to afford
exceptions, but you will need to basically duplicate the same check op+=
does, in user code; this may decrease performance, but will not allow a
buffer overflow in case you either forgot the check or got it wrong.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Andrey Semashev wrote:

> > void my_append( fixed_string<512> & s, std::string_view s1,
> > std::string_view s2 )
> > {
> >     if( s.size() + s1.size() + s2.size() > s.max_size() ) throw
> > std::length_error( "" );
> >
> >     s += s1;
> >     s += s2;
> > }
> >
> > Is this correct? (Spoiler: no.)
>
> I think, appending N strings still requires N tests, unless you know that
> the string sizes combined don't overflow.
>
>    size_t size_left = s.max_size() - s.size();
>    if (s1.size() > size_left) throw_length_error();
>    size_left -= s1.size();
>    if (s2.size() > size_left) throw_length_error();

Exactly. And the easiest and most readable way to get it right is just to do
the same op+= already would:

if( s1.size() > s.max_size() - s.size() ) throw std::length_error( "" );
s += s1;

if( s2.size() > s.max_size() - s.size() ) throw std::length_error( "" );
s += s2;

Incidentally, all the checks in the library seem wrong for this reason (they
check `size() + m > max_size()` instead of `m > max_size() - size()`.)


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
pt., 29 lis 2019 o 10:10 Peter Dimov via Boost <[hidden email]>
napisał(a):

> Andrzej Krzemienski wrote:
>
> > I suspect (I am not programming in an embedded system) that rather than
> > relying on __builtin_trap() or std::abort(), what you do is start
> treating
> > a `resize()` over `capacity()` as a precondition violation (a bug). And
> > this causes a different programming model and the organization of your
> > code.
>
> That was exactly why I wrote
>
> > > There's no need to afford exceptions, you just need to be able to
> afford
> > > the potential loss in performance, basically one branch per append if
> > > not heroically optimized away.
>
> That is: in order to use the library as presented, you don't need to
> afford
> exceptions, but you will need to basically duplicate the same check op+=
> does, in user code; this may decrease performance, but will not allow a
> buffer overflow in case you either forgot the check or got it wrong.
>

This is just performance aspect. Another one is correctness checking. If a
library adapted the model where over-resize is a bug, it can plant
sufficient platform-specific precondition annotations for the tools to be
able to detect user bugs. (e.g., when I put __builtin_unreachable() and
compile with UB-sanitizer).

Regards,
&rzej;

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On Wed, Nov 27, 2019 at 11:57 AM Zach Laine via Boost <[hidden email]>
wrote:

> Could you explain why the fixed_string API is not constexpr?  Is it for
> C++11 compatability?  Could you also explain how this meets the constexpr
> use case goal?
>

The library support down to C++11 when using boost, or C++17 at minimum in
standalone mode. As for why the lack of constexpr, it simply can be done
later.


> Would it be unreasonable to add op+ back in for operands of the same type?
> There's no difficulty determining the size of fixed_string<8>("foo") +
> fixed_string<8>("bar"), right?  That's no different
> from fixed_string<8>("foo") + "bar", which *is* supported.
>

There is no difficulty in determining the size, but there is the problem
that the size of the resulting string will be irrespective of the number of
characters contained within, which is not a problem for a string literal.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost-users] [review][fixed_string] FixedString review starts today

Boost - Dev mailing list
On Fri, Nov 29, 2019 at 10:50 AM Krystian Stasiowski via Boost
<[hidden email]> wrote:
> ...why the lack of constexpr, it simply can be done later.

In light of the use-cases brought up during review I think having the
noexcept and constexpr sooner rather than later is the best course of
action.

Thanks

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
123