Tuesday, November 28, 2017

Digest for comp.lang.c++@googlegroups.com - 25 updates in 9 topics

mirmikns@gmail.com: Nov 28 12:36AM -0800

Hello comrades.
 
I expected that std::nan is a constant (double) Nan, but it turns out that it is a function that takes a string argument and sets Nan with a mantissa corresponding to processing this string argument with a function strtod...
 
I only have one question ... Why would this be necessary ???
"James R. Kuyper" <jameskuyper@verizon.net>: Nov 28 11:22AM -0500

> Hello comrades.
 
> I expected that std::nan is a constant (double) Nan, but it turns out that it is a function that takes a string argument and sets Nan with a mantissa corresponding to processing this string argument with a function strtod...
 
> I only have one question ... Why would this be necessary ???
 
<https://en.wikipedia.org/wiki/IEEE_754#Formats>: "A NaN may carry a
payload that is intended for diagnostic information indicating the
source of the NaN." A NaN is represented by a biased-exponent field that
is filled with 1 bits, and a non-zero significand. The payload is stored
in the significand.
I'd cite IEEE 754 directly, if I could - but I don't have a copy of it.
I do have a copy of IEEE 854, which is a radix-independent variant of
IEEE 754, but I don't have it with me right now.
 
C++ does not mandate conformance with IEEE 754, but if
std::numeric_limits<T>::is_iec559 is true, then T conforms to IEC 559
(== ANSI/IEEE 754), and that is is overwhelmingly the most commonly
supported floating point standard. I think that some of the other
floating point standards may have a similar feature.
 
The specification for the strtod() function is incorporated by reference
from the C standard. Section 7.22.1.3p3 and p4 of the C standard specify
that a string starting with an optional sign followed by NAN will
produce a NAN, and that the "NAN" may optionally followed by sequence of
digits and nondigits - which sequences are allowed and what they mean is
implementation-defined (you might expect that everything is either a
digit or a non-digit, but that's not how those terms are defined. The
character '_', the roman letters 'a' through 'z' and 'A' through 'Z',
and any UCN are guaranteed to qualify as nondigits. Any other characters
that qualify as nondigits are implementation-defined - C standard
6.4.2.1p1).
 
The description of the iostreams library does not describe the handling
of NANs directly - it describes the relevant functions as equivalent to
calls to members of the printf() family of functions. The definitions of
those functions are incorporated by reference from the C standard.
Section 7.21.6.1p8 of the C standard specifies that if you print a NaN,
the output will start with an optional '-' followed by "nan" (if you use
%f, %e, %g, or %a) or "NAN" (if you use %F, %E, %G, or %A) optionally
followed by an implementation-defined sequence of characters.
 
Both ends of this process are entirely implementation-defined, which
allows an implementation to make full use of IEEE 754 NaNs with
payloads, or not, at the implementor's discretion. I would expect most
implementations which support NaN payloads to define the character
string produced by printf() of a NaN to match the string passed to
strtod() to create that NaN.
 
Thus, code which creates a NaN using strtod() can encode a limited
amount of information about the context in which it was created, which
can be decoded by printing the NaN.
ram@zedat.fu-berlin.de (Stefan Ram): Nov 28 06:03AM

>exactly the result that I expect, based upon the assumption that ::std::
>IS necessary, at least in some circumstances. Have I misunderstood
 
There is a conceptual difference:
 
::std::xyz
 
means:
 
"The name »xyz« from /the/ famous global std namespace."
 
, while
 
std::xyz
 
means:
 
"The name "xyz" from /any/ namespace "std" that happens
to in the scope of the usage of this expression".
 
Maybe the second possibility is a good thing sometimes,
when one wants to assign custom meanings to std::-names?
 
~~
 
WRT
 
using namespace ::std;
 
: even Bjarne Stroustrup uses it in his books. So it should
be accepted for tutorial examples or small or short-lived
programs. (I still do not use it in my own tutorial.)
 
~~
 
Pastability
 
A snippet like
 
::std::cout << 22 << '\n';
 
can be copied to every place:
 
- No need to verify that there is a
»using namespace ::std;« at the beginning
 
- No need to verify that there is no
(and will never be) another namespace
"std" in the vicinity.
 
A snippet like »cout << 22 << '\n'« would be more "fragile".
ram@zedat.fu-berlin.de (Stefan Ram): Nov 28 06:19AM

>similar issues would apply to the other four things that you want
>calculated, though I haven't bothered checking yet.
>Does this even remotely resemble what you're looking for?
 
I was starting to write about constructors for my
German-language C++ course.
 
Of course, I wanted to state the conditions under
which constructors are declared implicitly.
 
The rules seemed to be complicated. But maybe they
just /seemed/ to be complicated /to me/, but were
really quite simple for an expert who might be able
to give all the rules in just a few lines of text?
 
So, I had the idea to ask in this newsgroup.
 
But then I also thought that the English language
might add some ambiguity or vagueness to rules, and
that ambiguity or vagueness could be avoided by
expressing the rules in a more formal manner.
 
Since we already got C++ as a formal language,
it would be natural to express the rules using C++
herself.
 
From the rest of your reply I take it that the rules
are so complicated that even for an expert it is
not simple to write such a function.
 
Moreover, the rules might change in the future:
Scott Meyers wrote in 2014:
 
"At some point, analogous rules may be extended to the
copy operations, because C++11 deprecates the automatic
generation of copy operations for classes declaring copy
operations or a destructor."
 
Another complication is that in that point of my course, I
do not have explained all other parts of the language and
- wishing to avoid forward references - I still have to
exclude mentioning some parts of the language.
 
So, in the final end, it might come down to me having to use
some simplifications in that part of my course and only
mention some common situations in which certain special
member functions are generated or are not generated.
ram@zedat.fu-berlin.de (Stefan Ram): Nov 28 12:18PM

The Web page
 
en.cppreference.com/w/cpp/language/eval_order
 
says:
 
»In a shift operator expression E1<<E2 and E1>>E2, every
value computation and side-effect of E1 is sequenced
before every value computation and side effect of E2«.
 
A recent draft indeed says:
 
»The expression E1 is sequenced before the expression E2.«
 
in 8.8p4 (Shift operators).
 
. So is this defined now:
 
cout << ++i << i++;
 
? Here, an older gcc with -std=c++17 gives:
 
main.cpp
 
#include <iostream>
#include <ostream>
 
int main()
{ int i = 1;
::std::cout << i++ << ++i << '\n'; }
 
transcript
 
23
 
So, a real C++ compiler would print:
 
13
 
?
ram@zedat.fu-berlin.de (Stefan Ram): Nov 28 04:11PM

>Overloaded operators follow the rules for function calls. For example,
>if you overload operator&& it will not short-circuit even though the
>built-in one does.
 
I find in a recent draft a section
 
16.3.1.2 Operators in expressions [over.match.oper]
 
which says in p2:
 
|If either operand has a type that is a class or an
|enumeration, a user-defined operator function might be
|declared that implements this operator
 
...
 
|the operands are sequenced in the
|order prescribed for the built-in operator
 
.
Bo Persson <bop@gmb.dk>: Nov 28 03:46PM +0100

On 2017-11-28 13:18, Stefan Ram wrote:
 
> So, a real C++ compiler would print:
 
> 13
 
> ?
 
No. The rule is for the built in shift operator.
 
Overloaded operators follow the rules for function calls. For example,
if you overload operator&& it will not short-circuit even though the
built-in one does.
 
 
Bo Persson
Andrey Karpov <karpov2007@gmail.com>: Nov 28 05:43AM -0800

Today's article is somewhat unusual, if only because instead of reviewing one project, we'll be comparing three projects at once, looking for the one with the most interesting bugs and - which is of particular interest - the one with the highest code quality. The projects we are going to review are Firebird, MySQL, and PostgreSQL. So let's get started: https://www.viva64.com/en/b/0542/
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 28 05:57AM -0800

On Tuesday, November 28, 2017 at 8:44:04 AM UTC-5, Andrey Karpov wrote:
> Today's article .. we'll be comparing three projects at once...
 
How is this useful information? Bugs are bugs. Why would I care how
bugs in app1 relate to app2 or app3? This seems like info sanitizer
and compiler author developers would want to know so they could flag
them at compile time so that common types of coding patterns are identified
and reported on. It would be interesting for a software security overview,
but without context, without a personal impact ... how is it meaningful?
 
--
Rick C. Hodgin
Manfred <noname@invalid.add>: Nov 28 02:43PM +0100

On 11/27/2017 8:20 AM, Alf P. Steinbach wrote:
 
> Explicitly writing out the iterator type can be verbose and brittle, and
> so I wouldn't do that, but the question of how to communicate the
> constness of the iterator's referent is interesting.
 
[snip]
 
>         assert_is_const( *it );
>         //...
>     }
 
For this original problem, an even simpler writing would directly use
cbegin() and cend().
 
[snip]
 
 
> Much of the point is that one really doesn't care about the exact type
> of an iterator, and that it's desirable to /not/ know, because using
> that knowledge just makes the code brittle and possibly non-portable.
 
Indeed.
Christopher Pisz <christopherpisz@gmail.com>: Nov 27 04:31PM -0800

Everyone is quick to point out the "Rule of Zero" in code reviews, peer conversations, and Stack Overflow comments/answers.
 
I am not a believer. I'd like to be. Usually if enough people agree on something enough for it to get its own label and become an idiom, then it is well thought out....
 
So, let me explain my reason for not believing:
 
I cannot count the number of times I have been tasked to debug a crash dump from a production crash. While debugging said dump, I can look up and down the call stack and sometimes I have the need to see "When is this class being constructed?" Secondarily, I might need to see "What is its or its members addresses when it is?" This usually leads to some other place in the code after evidence that more instances are being created than should be, or when addresses or sizes are not what is expected.
 
This could also apply, when I want to see "When is this class being assigned to?"
 
As such, I've always implement all 5 methods, trivial or not, in order to provide a place to break in future debug sessions while reproducing the conditions in the dump without having to change the source. Without them, there would be no way (easily) to perform the above debugging session.
 
If you modify source in order to provide a line of code to break on, your crash dump is no longer usable with the source.
 
Now, some would say that this situation does not arise often enough for them to add more code, and more potential bugs, in the case of trivial constructors and assignment operators. However, I'd argue that one occasion having to explain to your superiors that you have to make another build, redeploy to production, reproduce the crash, and retrieve another dump, in order to even start debugging the problem, is enough to change one's outlook. That is not an enjoyable experience and it has occurred to me a number of times.
 
So, please make me a believer!
 
Tell me how I can accomplish the above described debugging session given a crash dump, when there is no line available to break on, after being a good boy and following the "Rule of Zero".
 
Namely:
 
1) Break any time any instance of a given class is being constructed without any lines of constructor code to break on.
 
2) Break any time any instance of a given class is being assigned to without any lines of assignment operator to break on.
 
I am using Visual Studio, and more specifically Visual Studio 2015. I've heard people in *nix actually have a means to accomplish the task without lines to break on. I've never had the pleasure of being in that environment though. I'd think that even if it is only a problem for Windows users, that is still a good enough number of people to raise the discussion.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 28 04:44AM +0100

On 11/28/2017 1:31 AM, Christopher Pisz wrote:
> in that environment though. I'd think that even if it is only a
> problem for Windows users, that is still a good enough number of
> people to raise the discussion.
 
Not addressing your problem but: it's more acute for basic types.
 
I once replaced a basic type with a full class type wrapper, for some
chosen variables, just for that kind of debugging. It wasn't my project.
These guys (re-) initialized their global variables from rather
inconceivable places at unpredictable times.
 
The order to not waste time on cleaning up the code was very firm. I
learned belatedly that it included not fixing bugs that prevented the
new code from functioning (that doesn't make sense, but not much did: my
theory is they were so incompetent as to be effectively insane). Half a
year later or so, questions about "what is this construction /for/"
appeared in this group, and I knew enough to answer them.
 
 
Cheers!,
 
- Alf
"Öö Tiib" <ootiib@hot.ee>: Nov 28 01:54AM -0800

On Tuesday, 28 November 2017 02:31:12 UTC+2, Christopher Pisz wrote:
 
<snipping to point>
 
> So, please make me a believer!
 
I use rule of zero as quite strong rule and can help to administer
it, but beware, my worldview is not a cult. It does not work on
belief. C++ is full of traps. Period. It is workable with awareness
understanding and on pile of tricks. If some "silver bullet" seems
to work always then it is actually superstition. You will be trapped
and then we all cheer "Gotcha!!". ;)
 
> without any lines of constructor code to break on.
 
> 2) Break any time any instance of a given class is being assigned to
> without any lines of assignment operator to break on.
 
Yes, our debuggers typically have no feature to break and to step
in implicitly generated code. When we only want to break or to trace
from the 5 then it is not too tricky to simplify it by typical separation
of concerns.
 
For example we can add a special member (or base) to our class with
all 5 members explicitly implemented. Implicitly-generated 5 are
required to call the 5 of such base or member and so we can break
in (or trace from) such stock class (or more likely template) instead
of implementing the 5 in every containing class.
 
That is already useful but we can further extend it with flexibility
features like:
1) to turn the fact of presence of such member on and off compile-time
2) to inject some other "indicating operations" besides trace into it
3) to select if it does its operation and from what members on and
off run-time
... and so on ...
 
As result instrumentation code can be left in forever and so can
be useful in unit-tests as well. Hopefully you see how to implement
such thing is lot more interesting and beneficial than to tediously
and error-pronely implement the 5 for each and every class.
James Kuyper <jameskuyper@verizon.net>: Nov 27 10:53PM -0500

> "::std::" prefix is unnecessary but "std::" isn't as "using namespace std;" is egregious.
 
I've heard that claim before, but I admit to being confused by it. The
following code compiles without warning or error messages and produces
exactly the result that I expect, based upon the assumption that ::std::
IS necessary, at least in some circumstances. Have I misunderstood
something?
 
 
#include <cstdio>
namespace kuyper {
namespace std {
void printf(const char *) { return;}
 
}
void func(void)
{
std::printf("Fake printf\n");
::std::printf("Real printf\n");
}
}
 
int main(void)
{
kuyper::func();
return 0;
}
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 28 06:40AM +0100

On 11/28/2017 4:53 AM, James Kuyper wrote:
> kuyper::func();
> return 0;
> }
 
No-one names a namespace `std`.
 
But that doesn't mean that Leigh is right about `using namespace std;`
always being ungood. That's like thinking pointers are always ungood,
say. To build a skyscraper in the same way as a small toy dollhouse,
just to be able to follow a simple set of mechanical rules for tool usage.
 
The way I look at code is more like overall structure first, and then
the details attach into slots of that structure here and there, for
whatever I look closer at. Some programmers say that verbosity with
everything qualified everywhere brings clarity, but that doesn't work
for me: it's just distracting redundancy. I guess they're focused on one
very tiny piece of code at a time, and then find it problematic to deal
with an unqualified `distance`, say, which, with a sufficiently narrowed
view just could be `std::distance`, or something else.
 
Cheers!,
 
- Alf
Juha Nieminen <nospam@thanks.invalid>: Nov 28 07:19AM

> exactly the result that I expect, based upon the assumption that ::std::
> IS necessary, at least in some circumstances. Have I misunderstood
> something?
 
Does the standard allow using the name 'std' for a namespace other
than the standard one? (I honestly don't know.)
Juha Nieminen <nospam@thanks.invalid>: Nov 28 07:25AM


> : even Bjarne Stroustrup uses it in his books. So it should
> be accepted for tutorial examples or small or short-lived
> programs. (I still do not use it in my own tutorial.)
 
The irony is that with very small snippets of code, using that
line often makes the code *longer*, not shorter.
 
Also, it doesn't increase readability. It only decreases it.
 
For some reason I can't really comprehend, many people have this
obstinate notion that using the "std::" previx somehow makes the
code harder to read. I have yet to see any of them giving a good
argument why. They just don't like it... because they don't like
it, period. No good reason.
 
In actuality the "std::" prefix works as a visual hint that
"a standard library name is being used here". It's a bit like
code coloring. It helps recognize standard library names with
a quick visual scan. Also, with names you don't recognize it
immediately tells you that it's a name from the standard library,
not some user-declared name somewhere else.
 
One some guy tried to prove that the "std::" prefix makes the
code unreadable and ugly by concocting a short piece of code
with something like ten uses of a standard library name.
Ironically, the version with the "std::" prefixes was actually
easier to understand than the one without them.
Ian Collins <ian-news@hotmail.com>: Nov 28 08:59PM +1300

On 11/28/2017 07:03 PM, Stefan Ram wrote:
> to in the scope of the usage of this expression".
 
> Maybe the second possibility is a good thing sometimes,
> when one wants to assign custom meanings to std::-names?
 
As Alf says, no one names a namespace `std`.
 
--
Ian.
David Brown <david.brown@hesbynett.no>: Nov 28 09:39AM +0100

On 28/11/17 07:03, Stefan Ram wrote:
 
> means:
 
> "The name "xyz" from /any/ namespace "std" that happens
> to in the scope of the usage of this expression".
 
Surely every C++ programmer knows not to make their own namespaces
called "std" ? There is no value in uglifying all your code to help
with a problem that does not exist.
 
 
> Maybe the second possibility is a good thing sometimes,
> when one wants to assign custom meanings to std::-names?
 
There are times when you want to overload std:: names, such as
std::swap. And then you want to be sure that you get that overload
/every/ time.
 
 
> : even Bjarne Stroustrup uses it in his books. So it should
> be accepted for tutorial examples or small or short-lived
> programs. (I still do not use it in my own tutorial.)
 
Code snippets in books are not examples of good real-world code. They
are to show a particular feature under discussion at the time.
 
 
> can be copied to every place:
 
> - No need to verify that there is a
> »using namespace ::std;« at the beginning
 
Yes, and "std::cout" can be pasted without verifying that "using
namespace std;" is in action.
 
No one argues against having the "std::" namespace prefix (sometimes you
want it, sometimes you want a "using"). But almost everyone disagrees
with your use of "::std::" instead of the normal "std::".
 
 
> - No need to verify that there is no
> (and will never be) another namespace
> "std" in the vicinity.
 
Have you ever seen any code that has its own "std" namespace with its
own identifiers, making "::std::" necessary?
 
David Brown <david.brown@hesbynett.no>: Nov 28 09:47AM +0100

On 28/11/17 08:19, Juha Nieminen wrote:
>> something?
 
> Does the standard allow using the name 'std' for a namespace other
> than the standard one? (I honestly don't know.)
 
I found this in the C++14 standard:
 
17.6.4.2.1
1
Overview
[constraints]
Namespace std
[namespace.std]
C++
The behavior of a
program is undefined if it adds declarations or definitions to namespace
std or to a
namespace within namespace std unless otherwise specified. A program may
add a template specialization
for any standard library template to namespace std only if the
declaration depends on a user-defined type
and the specialization meets the standard library requirements for the
original template and is not explicitly
prohibited.
 
 
I also had a quick look at some C++ standard library headers (from a gcc
installation). They are full of "std::", with the occasional
function-local using clause like "using std::swap;". Only once, in the
whole directory of include files, did I find "::std::" - it occurs in
"functional" and does not appear to be used intentionally.
 
So on at least one major C++ compiler, the whole standard library could
break if someone has been messing with "std" namespaces in such a way
that "::std::" will work but "std::" will not.
"James R. Kuyper" <jameskuyper@verizon.net>: Nov 27 10:40PM -0500

On 11/24/2017 06:49 AM, Stefan Ram wrote:
> MA = /* as above, but for the move assignment */
> DS = /* as above, but for the destructor */
 
> return make_tuple( DC, CC, CA, MC, MA, DS ); }
 
I'll handle the first one, DC, to give you an idea of what's actually
involved. I'm basing this off of C++2011.
 
auto explain
( bool DCu /* whether a default constructor is user-provided */,
bool Cu /* whether any constructor is user-provided */,
bool UVntdc /* Whether it is a union-like class that has a variant
member with a non-trivial default ctor. */,
bool NSDMNIR /* Whether any non-static data member with no
brace-or-equal_initializer is of reference type. */,
bool NVNSDMCQNBDc /* Whether all non-variant non-static data members
of const-qualified type (or array thereof) which have no
brace-or-equal-initializer have default constructors. */,
bool UVMCQ /* Whether it is a union and all members are of
const-qualified type (or array thereof) */,
bool NUMCQ /* Whether it is a non-union class and all members of any
anonymous union member have const-qualified type (or array
thereof) */,
bool BCNSDMNBDc /* Whether all direct or virtual base classes and
non-static data members with no brace-or-equal-initializer have
either a a default constructor, or an applicable overload that is
unambiguous and neither deleted nor inaccessible. */,
...
{
DC = /* 1 when a default constructor will be
implicitly-declared (or
 
2 if this happens, but is deprecated) or
 
0 when it will /not/ be implicitly-declared
(or implicitly-declared as deleted) under the
conditions described by the parameter values */
!Cu && // Implicitly declare (12.1p4)
// and not implicitly declared as having been deleted.
!(UVntdc || NSDMNIR || !NVNSDMCQNBDc || UVMCQ || NUMCQ
!BCNSDMNBDc);
 
I had to add seven arguments to your function, while making no use of
the only argument you probably thought was relevant. I expect that
similar issues would apply to the other four things that you want
calculated, though I haven't bothered checking yet.
 
Does this even remotely resemble what you're looking for?
 
It's entirely possible that one or more of the arguments I added is
described or used in exactly the opposite way that it should be - this
is the kind of question where that kind of mistake is easy to make.
However, I hope it's clear what the general framework of this expression
should look like.
David Brown <david.brown@hesbynett.no>: Nov 28 09:24AM +0100

On 28/11/17 07:19, Stefan Ram wrote:
> some simplifications in that part of my course and only
> mention some common situations in which certain special
> member functions are generated or are not generated.
 
I would have thought you'd be looking at type traits here. There are
three things you /don't/ want - one is for the user to have to supply a
long list of type attributes manually, when it is easy for them to make
mistakes. The next is to have complex logic like Ben showed you needed,
since it is easy for /you/ to make mistakes. And the third is to have
it all done at run-time instead of compile-time.
 
I am still not sure of what your use-cases are here. But I think you
want to start with the existing type traits. Then move on to
constructing your own type traits for anything missing. For things that
you can't figure out this way, you then want to ask if it really is a
useful feature.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 28 04:43AM +0100

On 11/27/2017 5:03 PM, Öö Tiib wrote:
 
> Does anyone know why move constructor and move assignment are implicitly
> noexcept(false)? By default (e.g. = default) these are also noexcept(true)
> when possible like the destructor is.
 
Today move semantics is a bit more, but originally it was an
optimization of copying.
 
As I recall, for that purpose some felt it was important that move
operations could be generated automatically by the compiler, wholly or
partially in terms of old possibly-throwing copy operations.
 
With such partially copy-based move operations, one hoped to get
significant speedups for legacy code just by recompiling, and over time
more of that the more old pure copy semantics in such code was
complemented with user defined move operations.
 
Regardless of whether my recollection of the rationale is correct,
having possibly throwing move operations was considered sufficiently
important to introduce a possible UB in std::vector reallocation, and to
generally just complicate things.
 
I think that decision was wrong: let's design this car partially as a
tractor so that it will work in some fashion also out in the fields, not
just on the road. Huh? What?
 
My 2c.
 
 
Cheers!,
 
- Alf
"Öö Tiib" <ootiib@hot.ee>: Nov 27 10:12PM -0800

On Monday, 27 November 2017 18:40:32 UTC+2, Daniel wrote:
> > I can hardly imagine any reasons to throw from ... move constructor
> > or move assignment.
 
> One reason, if move must replace an allocator, and propagate_on_container_move_assignment::value is false, the implementation may want to perform a copy, then copy can throw.
 
Thanks. Yes, C++17 made move assignments of the containers
that have allocator with 'propagate_on_container_move_assignment'
or 'is_always_equal' trait noexcept(true). That means 99.9% of
containers. Before C++17 all the move assignments of all containers
were noexcept(false).
 
We technically talk about unusual container whose owned resources
can not be transferred because of its odd allocator.
Why not to make such container simply not move-assignable?
"Öö Tiib" <ootiib@hot.ee>: Nov 27 11:45PM -0800

On Tuesday, 28 November 2017 05:43:40 UTC+2, Alf P. Steinbach wrote:
> significant speedups for legacy code just by recompiling, and over time
> more of that the more old pure copy semantics in such code was
> complemented with user defined move operations.
 
I have had same impression. The programmers do not typically care if
the underlying resources of throw-away objects are transferred or copied.
It is quite inconvenient to make some higher level logic dependent on
such low level details so it was quite bad legacy hack that did break
because of recompiling with C++11.

However we must care if something can throw exceptions or cannot and
(if possible) even what these exceptions are. ;)
 
> having possibly throwing move operations was considered sufficiently
> important to introduce a possible UB in std::vector reallocation, and to
> generally just complicate things.
 
Most robust would be to demand that move constructors and move assignments
simply may not throw. If author can't ensure that then '= delete' it and
done. The cloud of complications (like 'std::is_nothrow_move_assignable')
that no novice will ever learn to use correctly would vanish.
 
> I think that decision was wrong: let's design this car partially as a
> tractor so that it will work in some fashion also out in the fields, not
> just on the road. Huh? What?
 
Yes, and if they wanted actually ATV then why they did mount both the
spoiler and the snowplough to it? However I was not even dreaming of
anything charming. I was merely wondering why the move operations are
implicitly so inconveniently noexcept(false) while it is rather unusual
that these throw.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: