Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: template madness

213 views
Skip to first unread message

Alf P. Steinbach

unread,
Sep 1, 2018, 12:57:36 PM9/1/18
to
On 01.09.2018 17:31, Stefan Ram wrote:
> Can anyone here write an implementation of f so that
>
> f( g, 1, 2, 3, 4, 5, 6 )
>
> or
>
> f( g, 1, 2, 3, 4, 5, 6, 7 )
>
> will call
>
> g( 2, 4, 6 )
>
> , e.g., using every other argument with zero runtime
> overhead, e.g., using constexpr or templates.
>
> One can write f to get the parameters in a parameter
> pack and then possibly would need to write recursive
> partial specializations so as to unpack the parameter
> pack while building a new parameter pack with every
> other argument. (That last thing, building that new
> parameter pack and then using it for the call is what
> I have not yet learned to do!).
>
> If there would be an answer, I would then use it in
> an ongoing discussion in comp.lang.misc.
>
> I already found »struct alternating_tuple« at
>
> www.cplusplus.com/forum/general/135558/
>
> which might go somewhat in the direction intended.
>

#include <stddef.h> // size_t
#include <tuple> // std::(tie, tuple)
#include <utility> // std::make_index_sequence

namespace my
{
//using std::forward_as_tuple;
using std::make_index_sequence;
using std::tie;
using std::tuple;

namespace impl
{
using std::get;
using std::index_sequence;

template< class Func, class Argsref_tuple, size_t... Indices >
void f(
const Func& func,
const Argsref_tuple& args,
index_sequence<Indices...>
)
{ func( get<1 + 2*Indices>( args )... ); }
}

template< class Func, class... Args >
void f( const Func& func, Args&&... args )
{
impl::f(
func,
//forward_as_tuple<Args...>( args... ),
std::tuple<Args&&...>( std::forward<Args>( args )... ),
make_index_sequence<sizeof...(args)/2>()
);
}
} // namespace my

#include <stdio.h>
using Int = const int;

void g( Int a, Int b, Int c )
{
printf( "%d %d %d\n", a, b, c );
}

auto main()
-> int
{ using my::f; f( g, 1, 2, 3, 4, 5, 6 ); }


Cheers!,

- Alf

Juha Nieminen

unread,
Sep 1, 2018, 1:55:40 PM9/1/18
to
Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
> #include <stddef.h>
> #include <stdio.h>

Are you serious?

> using std::make_index_sequence;
> using std::tie;
> using std::tuple;
> using std::get;
> using std::index_sequence;

You wrote 102 characters, and 5 extra lines in total, in order to
save writing three instances of "std::" later. Thus you "saved"
a whopping -87 characters, without making the code any easier to
read or understand (but, arguably, the exact opposite):

> index_sequence<Indices...>
> { func( get<1 + 2*Indices>( args )... ); }
> make_index_sequence<sizeof...(args)/2>()

And then you aren't even consistent with it:

> std::tuple<Args&&...>( std::forward<Args>( args )... ),

I have a small suggestion. I know this is completely crazy, but...
How about you don't use the 'using' keyword for this purpose at all?
I know, completely crazy, but just think about it. I doubt that anybody
would get confused if the lines above had been:

std::index_sequence<Indices...>
{ func( std::get<1 + 2*Indices>( args )... ); }
std::make_index_sequence<sizeof...(args)/2>()

Jorgen Grahn

unread,
Sep 1, 2018, 2:33:12 PM9/1/18
to
On Sat, 2018-09-01, Juha Nieminen wrote:
> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>> #include <stddef.h>
>> #include <stdio.h>
>
> Are you serious?
>
>> using std::make_index_sequence;
>> using std::tie;
>> using std::tuple;
>> using std::get;
>> using std::index_sequence;
>
> You wrote 102 characters, and 5 extra lines in total, in order to
> save writing three instances of "std::" later. Thus you "saved"
> a whopping -87 characters, without making the code any easier to
> read or understand (but, arguably, the exact opposite):

+1 (except for the sarcasm, which IMO isn't helpful)

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Alf P. Steinbach

unread,
Sep 1, 2018, 4:06:30 PM9/1/18
to
On 01.09.2018 19:55, Juha Nieminen wrote:
> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>> #include <stddef.h>
>> #include <stdio.h>
>
> Are you serious?

Apparently it helped Stefan.


>> using std::make_index_sequence;
>> using std::tie;
>> using std::tuple;
>> using std::get;
>> using std::index_sequence;
>
> You wrote 102 characters, and 5 extra lines in total, in order to
> save writing three instances of "std::" later. Thus you "saved"
> a whopping -87 characters, without making the code any easier to
> read or understand (but, arguably, the exact opposite):

In my view it's idiotic to focus on numbers of characters.

Just my 2 øre.


Cheers & hth.,

- Alf

Mr Flibble

unread,
Sep 1, 2018, 6:27:42 PM9/1/18
to
I am sorry Alf but many members of the group agree that your coding style
is pathological in nature.

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That’s what I would say."

Alf P. Steinbach

unread,
Sep 2, 2018, 12:37:34 AM9/2/18
to
On 02.09.2018 00:27, Mr Flibble wrote:
>
> I am sorry Alf but many members of the group agree that your coding
> style is pathological in nature.

That's clearly intended as a personal attack on me, but ends up being a
personal attack on an unspecified “many” of the clc++ residents.

I've gotten used to your postings about sausages, your tirade of attacks
on the religious nutcases here, exceeding their original amount of noise
usually ten or twenty times, your personal attacks east and west and
whatever directions, your usually very foul language, etc., Leigh.

And mostly I just ignore it, kill the noise threads, sometimes killfile
people, for clearly you're out on a FISHING EXPEDITION where you want
some reaction. Just like, any reaction. So here is one; you're welcome.


Cheers!,

- Alf (laughing, just out of bed :-D )

Juha Nieminen

unread,
Sep 2, 2018, 3:17:53 AM9/2/18
to
Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
> On 01.09.2018 19:55, Juha Nieminen wrote:
>> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>>> #include <stddef.h>
>>> #include <stdio.h>
>>
>> Are you serious?
>
> Apparently it helped Stefan.

Including stdef.h (instead of cstdef) and stdio.h (instead of cstdio)
helped him, in your opinion?

I'm not even sure if stdef.h and stdio.h are even in the standard
anymore. (Even if they are, they are definitely not recommended.)

>> You wrote 102 characters, and 5 extra lines in total, in order to
>> save writing three instances of "std::" later. Thus you "saved"
>> a whopping -87 characters, without making the code any easier to
>> read or understand (but, arguably, the exact opposite):
>
> In my view it's idiotic to focus on numbers of characters.

You are missing the point. Citing the exact numbers is not the main
point. It's just a way of saying that not only is the use of 'using'
in order to not have to write the 'std::' prefix later rather pointless,
but ironically instead of saving trouble of writing more code, on the
contrary it only makes you write *more* code, not less, and thus is
a double fail.

Code does not become more readable by avoiding the 'std::' prefix.
On the contrary, it becomes *less* readable (because references to
standard library names are not being visually marked as such, making
them visually indistinguishable from custom names). And, as said,
ironically, with short code like this it only makes the code *longer*
(which kind of defeats the purpose of giving a short example), for
absolutely no benefit.

Alf P. Steinbach

unread,
Sep 2, 2018, 3:49:16 AM9/2/18
to
On 02.09.2018 09:17, Juha Nieminen wrote:
> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>> On 01.09.2018 19:55, Juha Nieminen wrote:
>>> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>>>> #include <stddef.h>
>>>> #include <stdio.h>
>>>
>>> Are you serious?
>>
>> Apparently it helped Stefan.
>
> Including stdef.h (instead of cstdef) and stdio.h (instead of cstdio)
> helped him, in your opinion?

You're stating that you have some strong opinions ...


> I'm not even sure if stdef.h and stdio.h are even in the standard
> anymore. (Even if they are, they are definitely not recommended.)

... AND that you don't know what you're talking about.


>>> You wrote 102 characters, and 5 extra lines in total, in order to
>>> save writing three instances of "std::" later. Thus you "saved"
>>> a whopping -87 characters, without making the code any easier to
>>> read or understand (but, arguably, the exact opposite):
>>
>> In my view it's idiotic to focus on numbers of characters.
>
> You are missing the point. Citing the exact numbers is not the main
> point. It's just a way of saying that not only is the use of 'using'
> in order to not have to write the 'std::' prefix later rather pointless,

Again you're have a strong opinion, and then make clear that you have no
idea what you're talking about.


> but ironically instead of saving trouble of writing more code, on the
> contrary it only makes you write *more* code, not less, and thus is
> a double fail.

You stated that the text size is "not the main point" (well it shouldn't
be a point at all unless the size differences are extreme), and now you
contradict that statement by focusing on the "trouble of writing more
code" as the main point.

That's your third direct self-contradiction in a very short stretch of
commentary.


> Code does not become more readable by avoiding the 'std::' prefix.
> On the contrary, it becomes *less* readable (because references to
> standard library names are not being visually marked as such, making
> them visually indistinguishable from custom names).

Here you're into partially subjective territory. Unfortunately the
subjective aspects of it appears to be all that you notice, except the
in-your-face incorrect assertion that "references to standard library
names are not being visually marked as such". They're explicitly listed,
which is one way, plus your editor or IDE marks them, that's another.


> And, as said,
> ironically, with short code like this it only makes the code *longer*
> (which kind of defeats the purpose of giving a short example), for
> absolutely no benefit.

Uh. That's not an issue for me.

Count your characters and be happy, but don't demand that I do that, please.


Cheers!,

- Alf

Ian Collins

unread,
Sep 2, 2018, 4:13:00 AM9/2/18
to
On 02/09/18 19:17, Juha Nieminen wrote:
> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>> On 01.09.2018 19:55, Juha Nieminen wrote:
>>> Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>>>> #include <stddef.h>
>>>> #include <stdio.h>
>>>
>>> Are you serious?
>>
>> Apparently it helped Stefan.
>
> Including stdef.h (instead of cstdef) and stdio.h (instead of cstdio)
> helped him, in your opinion?
>
> I'm not even sure if stdef.h and stdio.h are even in the standard
> anymore. (Even if they are, they are definitely not recommended.)

They are and they are still recommended in more than a few coding
standards (including ours). If you are going to use C standard library
functions, you may as will use the C headers. I for one consider the
C++ wrappers a mistake.

--
Ian.

Melzzzzz

unread,
Sep 2, 2018, 4:31:34 AM9/2/18
to
Somewhere I saw that cheader are not favored any more... header.h is in
;)

--
press any key to continue or any other to quit...

Öö Tiib

unread,
Sep 2, 2018, 6:38:19 AM9/2/18
to
Team has to agree if and what they use from C standard library and
how. If they decide to use <cheaders> then they should also use
`std::int32_t` and `std::ptrdiff_t` qualified because <cheaders> are
not required to define global namespace versions. Couple using
declarations or verbosity of `std::int32_t` are matter of taste.
Is it `std::get` or `my::impl::get`? That is bike-shedding of low
importance, consistency is more important.

OTOH functions with a lot of (like 7 or 8) parameters are IMHO not
matter of taste. These tend to actually make code harder to read and
to reason about. This thread was about how to implement such
annoying functions with low run-time overhead.

Mr Flibble

unread,
Sep 2, 2018, 10:57:15 AM9/2/18
to
That is all well and good but it doesn't change the fact that your coding
style is pathological in nature.

Vir Campestris

unread,
Sep 2, 2018, 4:41:51 PM9/2/18
to
Juha, Alf, please keep it calm.

I want to hear from both of you. Even though I don't always agree.

Andy

Juha Nieminen

unread,
Sep 3, 2018, 1:14:46 AM9/3/18
to
Ian Collins <ian-...@hotmail.com> wrote:
>> I'm not even sure if stdef.h and stdio.h are even in the standard
>> anymore. (Even if they are, they are definitely not recommended.)
>
> They are and they are still recommended in more than a few coding
> standards (including ours).

Does the same coding standard recommend using "using namespace std;"?

Doesn't sound like a very good coding standard to me...

> If you are going to use C standard library
> functions, you may as will use the C headers.

They are C++ standard library functions because they are defined in the
C++ standard. If you are writing C++, use C++ headers.

Ian Collins

unread,
Sep 3, 2018, 1:35:08 AM9/3/18
to
On 03/09/18 17:14, Juha Nieminen wrote:
> Ian Collins <ian-...@hotmail.com> wrote:
>>> I'm not even sure if stdef.h and stdio.h are even in the standard
>>> anymore. (Even if they are, they are definitely not recommended.)
>>
>> They are and they are still recommended in more than a few coding
>> standards (including ours).
>
> Does the same coding standard recommend using "using namespace std;"?

No, it forbids it.

> Doesn't sound like a very good coding standard to me...

It's quite good at a mere page and a bit.

>> If you are going to use C standard library
>> functions, you may as will use the C headers.
>
> They are C++ standard library functions because they are defined in the
> C++ standard. If you are writing C++, use C++ headers.

std::size_t? No thanks!

--
Ian.


Juha Nieminen

unread,
Sep 3, 2018, 2:26:51 AM9/3/18
to
Ian Collins <ian-...@hotmail.com> wrote:
>> They are C++ standard library functions because they are defined in the
>> C++ standard. If you are writing C++, use C++ headers.
>
> std::size_t? No thanks!

What problem do you find with that? I use it all the time. I have had
no problems with it.

peter koch

unread,
Sep 3, 2018, 6:06:04 AM9/3/18
to
mandag den 3. september 2018 kl. 07.14.46 UTC+2 skrev Juha Nieminen:
> Ian Collins <ian-...@hotmail.com> wrote:
> >> I'm not even sure if stdef.h and stdio.h are even in the standard
> >> anymore. (Even if they are, they are definitely not recommended.)
> >
> > They are and they are still recommended in more than a few coding
> > standards (including ours).
>
> Does the same coding standard recommend using "using namespace std;"?
>
> Doesn't sound like a very good coding standard to me...

Including the CPP versions of C headers does not guarantee that the global namespace is not polluted. I believe that this is a strong argument for preferring the C-headers. How else would you guard yourself against stuff breaking up when e.g. changing between compilers?

Chris Vine

unread,
Sep 3, 2018, 6:33:36 AM9/3/18
to
It can also be necessary to use the C headers in C++ where the code is
governed by more than one standard. Say you are using the POSIX
function strdup() in your C++ code[1]. That is in the C/POSIX header
string.h.

Can you reliably (in a cross-implementation way) call strdup() by
including the cstring header, and if so is strdup() placed in namespace
std? Dunno, strdup() is not incorporated by the C++ standard at any
rate. If you have to include string.h to capture strdup(), are you
really going to include cstring to capture also, say, strcpy() in the
same code?

This is not wholly rhetorical. What do other people do?

Chris

[1] Yes there are other ways of duplicating strings in C++ - you might
just copy std::string objects. But strdup() can often be useful when
interfacing with C libraries.

Paavo Helde

unread,
Sep 3, 2018, 6:54:04 AM9/3/18
to
On 3.09.2018 13:33, Chris Vine wrote:

> Say you are using the POSIX function strdup() in your C++ code[1].
> That is in the C/POSIX headerstring.h.
[...]
> This is not wholly rhetorical. What do other people do?

Why, perform code cleanup and replace strdup() with a C++ std::string
creation, of course.

BTW, I'm in the camp of including <header.h>, if I'm using C functions
in C++ code then I should be brave enough to admit it and not trying to
masquerade them with std::. Strdup() is just probably the most useless
example.

Chris Vine

unread,
Sep 3, 2018, 10:36:59 AM9/3/18
to

Paavo Helde

unread,
Sep 3, 2018, 12:12:50 PM9/3/18
to
I'm curious where it can be "often useful"?

I can see using strdup might be useful if a C library function has a
string input parameter which is assumed to be released inside the
library, or at least is assumed to be not released by the caller. There
are some C interfaces like that, e.g. POSIX putenv() (which basically
mandates memory leaks and should be replaced by setenv() anyway), and
rl_completion_matches in the readline library interface. However, I
would not use the word "often" here.

Not to speak about that strdup() is more verbose to use than std::string
as its return value needs to be explicitly checked for errors.


Chris Vine

unread,
Sep 3, 2018, 1:49:49 PM9/3/18
to
On Mon, 03 Sep 2018 19:12:39 +0300
Paavo Helde <myfir...@osa.pri.ee> wrote:
> On 3.09.2018 17:36, Chris Vine wrote:
> > On Mon, 03 Sep 2018 13:53:54 +0300
> > Paavo Helde <myfir...@osa.pri.ee> wrote:
> >
> >> On 3.09.2018 13:33, Chris Vine wrote:
> >>
> >>> Say you are using the POSIX function strdup() in your C++ code[1].
> >>> That is in the C/POSIX headerstring.h.
> >> [...]
> >>> This is not wholly rhetorical. What do other people do?
> >>
> >> Why, perform code cleanup and replace strdup() with a C++ std::string
> >> creation, of course.
> >>
> >> BTW, I'm in the camp of including <header.h>, if I'm using C functions
> >> in C++ code then I should be brave enough to admit it and not trying to
> >> masquerade them with std::. Strdup() is just probably the most useless
> >> example.
> >
> > "Yes there are other ways of duplicating strings in C++ - you might
> > just copy std::string objects. But strdup() can often be useful when
> > interfacing with C libraries".
>
> I'm curious where it can be "often useful"?

For example, when passing a non-literal string datum to a callback in a
C library. (Callbacks often have to take ownership of their data,
because they control lifetime and not you.)

Juha Nieminen

unread,
Sep 4, 2018, 1:44:11 AM9/4/18
to
peter koch <peter.ko...@gmail.com> wrote:
> Including the CPP versions of C headers does not guarantee that the
> global namespace is not polluted. I believe that this is a strong
> argument for preferring the C-headers. How else would you guard
> yourself against stuff breaking up when e.g. changing between
> compilers?

Does including the .h files guarantee that the names will also be in the
std namespace? If not, what if you *want* to use the std:: prefix?

David Brown

unread,
Sep 4, 2018, 2:16:04 AM9/4/18
to
The C++ standard (quoting from N3797, C++14, since that's what I have
handy) says:


17.6.1.2 Headers
Each element of the C ++ standard library is declared or defined (as
appropriate) in a header.
The C ++ standard library provides 55 C ++ library headers, as shown in
Table 14.
The facilities of the C standard Library are provided in 26 additional
headers, as shown in Table 15.
Except as noted in Clauses 18 through 30 and Annex D, the contents of
each header cname shall be the same
as that of the corresponding header name.h, as specified in the C
standard library (1.2) or the C Unicode TR, as appropriate, as if by
inclusion. In the C ++ standard library, however, the declarations
(except for
names which are defined as macros in C) are within namespace scope
(3.3.6) of the namespace std. It is
unspecified whether these names are first declared within the global
namespace scope and are then injected
into namespace std by explicit using-declarations.


To me, that says that <cstdint> guarantees to have the names in std::
while <stdint.h> guarantees to have the names in the global namespace.
<cstdint> may also have them in the global namespace, but does not have
to, while <stdint.h> could also have them in std:: but does not have to.

In fact, I don't think a C++ implementation has to have <stdint.h> at
all - only the <cstdint> style headers. But I'd be surprised to find a
C++ implementation that is not also a C implementation.

Ian Collins

unread,
Sep 4, 2018, 3:32:29 AM9/4/18
to
I just find it odd, probably because I also work with C and POSIX code.

--
Ian.

Alf P. Steinbach

unread,
Sep 4, 2018, 4:14:48 AM9/4/18
to
On 04.09.2018 07:43, Juha Nieminen wrote:
> peter koch <peter.ko...@gmail.com> wrote:
>> Including the CPP versions of C headers does not guarantee that the
>> global namespace is not polluted. I believe that this is a strong
>> argument for preferring the C-headers. How else would you guard
>> yourself against stuff breaking up when e.g. changing between
>> compilers?
>
> Does including the .h files guarantee that the names will also be in the
> std namespace?

No.


> If not, what if you *want* to use the std:: prefix?

Include both, or better, include a wrapper that includes both.

Oh look!

<url:
https://github.com/alf-p-steinbach/Wrapped-stdlib/tree/master/source/c>

However, that code includes an overly optimistic attempt to foil
Microsoft's attempt at steering people over to their vendor lock-in
traps via spurious and misleading sillywarnings. I now regret attempting
it. It didn't work: the solutions to avoid that diagnostics noise must
be adjusted at roughly every new Visual C++ compiler update, so it's
best done via the build system and not attempted in code.

Sorry 'bout that.

Chris Vine

unread,
Sep 4, 2018, 1:12:47 PM9/4/18
to
On Tue, 4 Sep 2018 08:15:53 +0200
David Brown <david...@hesbynett.no> wrote:
[snip]
> In fact, I don't think a C++ implementation has to have <stdint.h> at
> all - only the <cstdint> style headers. But I'd be surprised to find a
> C++ implementation that is not also a C implementation.

My reading of Annex D5 of C++14 is that stdint.h must be supplied by a
conforming implementation (along with the other 26 C headers in
'name.h' form), and that the things declared or defined there must be in
the global namespace.

james...@alumni.caltech.edu

unread,
Sep 4, 2018, 1:48:59 PM9/4/18
to
On Tuesday, September 4, 2018 at 2:16:04 AM UTC-4, David Brown wrote:
...
> In fact, I don't think a C++ implementation has to have <stdint.h> at
> all - only the <cstdint> style headers. But I'd be surprised to find a
> C++ implementation that is not also a C implementation.

From n4762.pdf:
"The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety." (15.1p1)
"For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 136." (D.6p1)

Table 136 include <stdint.h>. This is not new in this draft version - it's been around for a while, though I'm not sure which was the first version to mandate provision of <stdint.h>.

Alf P. Steinbach

unread,
Sep 4, 2018, 4:08:26 PM9/4/18
to
On 04.09.2018 08:15, David Brown wrote:
> [snip]
> > To me, that says that <cstdint> guarantees to have the names in std::
> while <stdint.h> guarantees to have the names in the global namespace.
> <cstdint> may also have them in the global namespace, but does not have
> to, while <stdint.h> could also have them in std:: but does not have to.

Yes.


> In fact, I don't think a C++ implementation has to have <stdint.h> at
> all - only the <cstdint> style headers.  But I'd be surprised to find a
> C++ implementation that is not also a C implementation.

The C++ ".h" headers are not part of the C implementation, except to the
degree that each vendor finds it possible to reuse code (in particular,
by just letting the C++ ".h" header include the C ".h" header and add
whatever additional stuff that's required in C++, such as overloads).

The C++ ".h" headers define a lot of stuff that wouldn't compile as C,
including function overloads.

They're required headers, and the language being built on the idea of
reusing C libraries, means that one needs to use C language headers that
in turn include ".h" headers, from C++, which means they'll not go away.

One might wonder what the deprecation in 1998 then was all about. I
think it's simple, that some committee members /envisioned/ the
possibility of clean C++ code with all standard library names in
namespace `std`. The compiler vendors' total unwillingness to provide
clean conforming "c..." headers shattered that dream.

Since C++11, where practical reality ("c..." headers polluting the
global namespace) was allowed by the standard, so that the "c..."
headers no longer have any purpose, and especially so that refraining
from using the ".h" headers no longer has any purpose, one might wonder
what the continued deprecation is all about. I think that may be
political. Or it may be, and writing this now it seems probable, simply
that nobody's willing to front and argue the case; after all, things
work now, there's no technical problem to be solved, just a perception.

Cheers!,

- Alf

Öö Tiib

unread,
Sep 4, 2018, 5:39:01 PM9/4/18
to
On Tuesday, 4 September 2018 23:08:26 UTC+3, Alf P. Steinbach wrote:
>
> Since C++11, where practical reality ("c..." headers polluting the
> global namespace) was allowed by the standard, so that the "c..."
> headers no longer have any purpose, and especially so that refraining
> from using the ".h" headers no longer has any purpose, one might wonder
> what the continued deprecation is all about. I think that may be
> political. Or it may be, and writing this now it seems probable, simply
> that nobody's willing to front and argue the case; after all, things
> work now, there's no technical problem to be solved, just a perception.

Several people have already expressed the purpose of <cheaders>. They
want to write "std::" and <cheaders> provide that opportunity. It
makes code easier to read for them. This is matter of taste
and about taste it is easy to fight but impossible to argue.

Most of C library names are utter Klingon recognizable from afar
without any "std::" needed. But ... about dozen or so names in it are
common words. You know ... "time", "clock", "abort", "exit", "free",
"system", "floor", "round" &c. Such can clash and I've seen
intermediate maintainers confusing themselves for a hour or couple
because of hiding those with a more local name. So at least "::"
prefix should be used and then it is only "std" that remains.

Juha Nieminen

unread,
Sep 5, 2018, 1:02:16 PM9/5/18
to
Öö Tiib <oot...@hot.ee> wrote:
> Most of C library names are utter Klingon recognizable from afar
> without any "std::" needed. But ... about dozen or so names in it are
> common words. You know ... "time", "clock", "abort", "exit", "free",
> "system", "floor", "round" &c. Such can clash and I've seen
> intermediate maintainers confusing themselves for a hour or couple
> because of hiding those with a more local name. So at least "::"
> prefix should be used and then it is only "std" that remains.

It doesn't exactly help that the C standard library doesn't use
a consistent naming convention.

For example, FILE is not a macro (and thus "std::FILE" is fine).
On the other hand, assert() is a macro (and thus "std::assert"
just cannot work).

Mr Flibble

unread,
Sep 5, 2018, 1:33:37 PM9/5/18
to
1) Don't use FILE; use C++ wrappers of FILE (std::fstream et al).

2) Don't use assert as it is considered harmful; throw an exception instead.

Öö Tiib

unread,
Sep 5, 2018, 2:19:39 PM9/5/18
to
On Wednesday, 5 September 2018 20:33:37 UTC+3, Mr Flibble wrote:
>
> 2) Don't use assert as it is considered harmful; throw an exception instead.

Throwing exception is even worse than assert. Exception reports nothing
and when there happens to be some catch(...) {cleanse();throw;} on the
way out then it spoils the crash dump as well.

Proper way of handling programming errors run time is to report (or log)
the error and to kill the program. That can't be done in centralized
manner and so has to be implemented into every program anew. Reporting
just can not be for example injected into std::terminate since that
does not accept any arguments.

Ian Collins

unread,
Sep 5, 2018, 3:28:42 PM9/5/18
to
On 06/09/18 05:33, Mr Flibble wrote:
>
> 2) Don't use assert as it is considered harmful; throw an exception instead.

Considered harmful by whom?

--
Ian

Jorgen Grahn

unread,
Sep 5, 2018, 4:11:21 PM9/5/18
to
On Tue, 2018-09-04, Öö Tiib wrote:
...
> Several people have already expressed the purpose of <cheaders>. They
> want to write "std::" and <cheaders> provide that opportunity. It
> makes code easier to read for them. This is matter of taste
> and about taste it is easy to fight but impossible to argue.
>
> Most of C library names are utter Klingon recognizable from afar
> without any "std::" needed.

I think that's a key point. The C names tend to be recognizable and
odd, or at least well-known like "free" and the other ones Tiib
mentioned.

C++ standard library names are in a namespace. So if you shave off
the namespace all that's left is often a common name (find, copy,
read, ...) which you want to use for things in your own code. At least
/I/ want to use them: I prefer to read short names without superfluous
information, and I don't use CamelCase for functions, so my names tend
to be similar to the standard library's.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Jorgen Grahn

unread,
Sep 5, 2018, 4:21:33 PM9/5/18
to
If I use POSIX functions, I use the POSIX headers which are documented
to pull them in.

Using your example, if I used strdup() and strerror() in some source
file, I'd pretend both as merely POSIX functions, and pull them in
using <string.h>.

This is rarely or never a problem for me, and I still get to use the
<cfoo> headers a lot.

Scott Lurndal

unread,
Sep 5, 2018, 4:23:47 PM9/5/18
to
Ian Collins <ian-...@hotmail.com> writes:
> Thunderbird/52.9.1
>In-Reply-To: <WoCdnfKZHPj8jg3G...@giganews.com>
>Content-Language: en-US
>X-Received-Bytes: 1535
>X-Received-Body-CRC: 3264370011
>
>On 06/09/18 05:33, Mr Flibble wrote:
>>
>> 2) Don't use assert as it is considered harmful; throw an exception instead.
>
>Considered harmful by whom?

While I disgree with the 'throw an exception instead', I don't like
to see assert() used in production code - it is very user unfriendly
and doesn't provide sufficient information for a user to create a
defect report from. Use it for development testing, but build the
production software with -DNDEBUG.

Most places where an assert is used, the proper recovery code could
be added with a modicum of extra effort.

Ian Collins

unread,
Sep 5, 2018, 4:31:48 PM9/5/18
to
Most but not all; sometimes we need to protect against the impossible!

While an assertion may be user unfriendly, crashing the system with a
stack-trace and core dump is very developer friendly. Throwing an
exception looses the forensic trail to the crash.

--
Ian.

Alf P. Steinbach

unread,
Sep 5, 2018, 6:07:23 PM9/5/18
to
On 05.09.2018 22:23, Scott Lurndal wrote:
> [snip]
>
> While I disgree with the 'throw an exception instead', I don't like
> to see assert() used in production code - it is very user unfriendly
> and doesn't provide sufficient information for a user to create a
> defect report from. Use it for development testing, but build the
> production software with -DNDEBUG.

If that refers to use of `assert`on its own, it means that where
otherwise an assertion would fire, the user just gets wrong but perhaps
not obviously wrong results (Murphy's law would skew reality in the
direction of the not obviously wrong results, and mostly where they harm
the most). Maybe later also a crash or hang. IMO that's a very bad idea,
but maybe you're talking about a double-whammy assert + something, where
the something might be a "hard" exception or termination with logging or
termination with optional restart and logging.


> Most places where an assert is used, the proper recovery code could
> be added with a modicum of extra effort.

A failed assertion usually means that at least one critical assumption
did not hold.

AFAIK local recovery from incorrect critical assumptions, is usually not
practically possible.


Cheers!

- Alf

Juha Nieminen

unread,
Sep 6, 2018, 4:46:53 AM9/6/18
to
Mr Flibble <flibbleREM...@i42.co.uk> wrote:
>> It doesn't exactly help that the C standard library doesn't use
>> a consistent naming convention.
>>
>> For example, FILE is not a macro (and thus "std::FILE" is fine).
>> On the other hand, assert() is a macro (and thus "std::assert"
>> just cannot work).
>
> 1) Don't use FILE; use C++ wrappers of FILE (std::fstream et al).
>
> 2) Don't use assert as it is considered harmful; throw an exception instead.

Way to completely miss my point.

Anyway, if we are going to that tangent, unfortunately the C file
functions are still faster than the C++ ones (even though the gap
has gotten smaller over the decades). If you want the absolutely
fastest file reading speed in your program, you'll probably have
to use the C file handling functions (especially std::fread).
And yes, there are many situations where you really want or even
need the fastest possible file reading and writing.

Juha Nieminen

unread,
Sep 6, 2018, 4:55:10 AM9/6/18
to
Ian Collins <ian-...@hotmail.com> wrote:
> Most but not all; sometimes we need to protect against the impossible!
>
> While an assertion may be user unfriendly, crashing the system with a
> stack-trace and core dump is very developer friendly. Throwing an
> exception looses the forensic trail to the crash.

In general, use assert() for situations that indicate such a serious
bug in the program that there is no recovery possible and the only
viable and sane thing to do is to just terminate the program there,
because it can't possibly work correctly anymore. Most useful at the
development stage, of course. (Whether the assertions should be left
in the final published product is another complex question.)

Throw an exception for situations that are fatal errors, but can
be ostensibly recovered from. In some cases it may be the handiest way
for a library to indicate to the calling code that something went
horribly wrong and the requested thing cannot be done. (This may happen
in a situation where it's just not feasible to simply return some kind
of error code from the library.) A memory allocation error, which the
standard library containers throw when it happens, might be the
quintessential example: The container has fatally failed to perform
the requested operation, and cannot possibly continue to work as it
should, but this should cause the program to simply crash. Instead,
the calling code is given the choice to recover from this situation.
Since there's a myriad of places where this error may happen, many of
which cannot possibly just return an error code (such as a copy
constructor, for instance), throwing an exception is the most viable
strategy. If the calling code wants to deal with this situation
gracefully, it can.

David Brown

unread,
Sep 6, 2018, 6:08:47 AM9/6/18
to
I would expect that the fastest way to access files is going to vary by
OS, by access type, and even by filesystem type. mmap() is often going
to be faster than any file read or write function for random access -
but perhaps for compressed or COW filesystems you are better reading the
file in as one lump and writing a new copy, rather than modifying the file.

And for files on a disk (even an SSD), I would expect the difference in
processor time between the C functions (which will be thin wrappers over
the OS API calls) and the C++ functions (which might be thicker
wrappers) will be negligible.

james...@alumni.caltech.edu

unread,
Sep 6, 2018, 8:54:54 AM9/6/18
to
On Thursday, September 6, 2018 at 4:55:10 AM UTC-4, Juha Nieminen wrote:
> Ian Collins <ian-...@hotmail.com> wrote:
> > Most but not all; sometimes we need to protect against the impossible!
> >
> > While an assertion may be user unfriendly, crashing the system with a
> > stack-trace and core dump is very developer friendly. Throwing an
> > exception looses the forensic trail to the crash.
>
> In general, use assert() for situations that indicate such a serious
> bug in the program that there is no recovery possible and the only
> viable and sane thing to do is to just terminate the program there,
> because it can't possibly work correctly anymore. Most useful at the
> development stage, of course. (Whether the assertions should be left
> in the final published product is another complex question.)

One of the key features of assert() is the ability to turn it off by
#defining NDEBUG. If you have no intention of ever using that feature,
you should define your own assert-like macro that doesn't have that
feature.

My biggest problem with assert() is that I can't imagine any context in
which what assert() does is what I would want my program to do, starting
with the fact that the date isn't in ISO 8601 format. I generally prefer
that, no matter how bad the problem, my program doesn't exit without
first sending a message somewhere that contains information about the
run-time context in which it failed. For instance, if assert(a<b) would
be triggered, I'd want information about the current values of a and b.
And I almost always want it to perform needed clean-up.

Scott Lurndal

unread,
Sep 6, 2018, 8:55:39 AM9/6/18
to
Juha Nieminen <nos...@thanks.invalid> writes:
>Mr Flibble <flibbleREM...@i42.co.uk> wrote:
>>> It doesn't exactly help that the C standard library doesn't use
>>> a consistent naming convention.
>>>
>>> For example, FILE is not a macro (and thus "std::FILE" is fine).
>>> On the other hand, assert() is a macro (and thus "std::assert"
>>> just cannot work).
>>
>> 1) Don't use FILE; use C++ wrappers of FILE (std::fstream et al).
>>
>> 2) Don't use assert as it is considered harmful; throw an exception instead.
>
>Way to completely miss my point.
>
>Anyway, if we are going to that tangent, unfortunately the C file
>functions are still faster than the C++ ones (even though the gap
>has gotten smaller over the decades). If you want the absolutely
>fastest file reading speed in your program, you'll probably have
>to use the C file handling functions (especially std::fread).

Or the POSIX functions, esp. mmap.

Juha Nieminen

unread,
Sep 7, 2018, 2:17:26 AM9/7/18
to
Scott Lurndal <sc...@slp53.sl.home> wrote:
>>Anyway, if we are going to that tangent, unfortunately the C file
>>functions are still faster than the C++ ones (even though the gap
>>has gotten smaller over the decades). If you want the absolutely
>>fastest file reading speed in your program, you'll probably have
>>to use the C file handling functions (especially std::fread).
>
> Or the POSIX functions, esp. mmap.

If you are making a closed program for a limited number of platforms,
you can of course do that. However, if you want to write portable
code, then that's not an option.

Jorgen Grahn

unread,
Sep 7, 2018, 8:02:21 AM9/7/18
to
On Thu, 2018-09-06, james...@alumni.caltech.edu wrote:
> On Thursday, September 6, 2018 at 4:55:10 AM UTC-4, Juha Nieminen wrote:
>> Ian Collins <ian-...@hotmail.com> wrote:
>> > Most but not all; sometimes we need to protect against the impossible!
>> >
>> > While an assertion may be user unfriendly, crashing the system with a
>> > stack-trace and core dump is very developer friendly. Throwing an
>> > exception looses the forensic trail to the crash.
>>
>> In general, use assert() for situations that indicate such a serious
>> bug in the program that there is no recovery possible and the only
>> viable and sane thing to do is to just terminate the program there,
>> because it can't possibly work correctly anymore. Most useful at the
>> development stage, of course. (Whether the assertions should be left
>> in the final published product is another complex question.)
>
> One of the key features of assert() is the ability to turn it off by
> #defining NDEBUG. If you have no intention of ever using that feature,
> you should define your own assert-like macro that doesn't have that
> feature.

Why? I don't define my own std::printf() just because I never use the
%g format specifier.

More seriously, shipping with assert() enabled may be something you
dislike, but it doesn't violate the semantics of assert() itself.
Unlike many other common assert usage patterns.

Scott Lurndal

unread,
Sep 7, 2018, 8:58:25 AM9/7/18
to
Juha Nieminen <nos...@thanks.invalid> writes:
>Scott Lurndal <sc...@slp53.sl.home> wrote:
>>>Anyway, if we are going to that tangent, unfortunately the C file
>>>functions are still faster than the C++ ones (even though the gap
>>>has gotten smaller over the decades). If you want the absolutely
>>>fastest file reading speed in your program, you'll probably have
>>>to use the C file handling functions (especially std::fread).
>>
>> Or the POSIX functions, esp. mmap.
>
>If you are making a closed program for a limited number of platforms,

*snort* mmap is portable to a very large number of platforms - there
is only one that it is not directly portable to (but could be shimmed
on windows).

>you can of course do that. However, if you want to write portable
>code, then that's not an option.

Sure it is. Abstract it in a class (we have a class called c_osdep)
which is dependent upon the OS. Use the windows mapping functions
in the windows version of the class, and the posix functions in the
posix version of the class. The remaining code is then portable.

Nothing useful can be done with just the facilities provided by the
C or C++ standards in my line of work.

james...@alumni.caltech.edu

unread,
Sep 7, 2018, 9:16:55 AM9/7/18
to
On Friday, September 7, 2018 at 8:02:21 AM UTC-4, Jorgen Grahn wrote:
> On Thu, 2018-09-06, james...@alumni.caltech.edu wrote:
> > On Thursday, September 6, 2018 at 4:55:10 AM UTC-4, Juha Nieminen wrote:
...
> >> In general, use assert() for situations that indicate such a serious
> >> bug in the program that there is no recovery possible and the only
> >> viable and sane thing to do is to just terminate the program there,
> >> because it can't possibly work correctly anymore. Most useful at the
> >> development stage, of course. (Whether the assertions should be left
> >> in the final published product is another complex question.)
> >
> > One of the key features of assert() is the ability to turn it off by
> > #defining NDEBUG. If you have no intention of ever using that feature,
> > you should define your own assert-like macro that doesn't have that
> > feature.
>
> Why? I don't define my own std::printf() just because I never use the
> %g format specifier.

I consider the fact that it can be turned off by #defining NDEBUG to be
a very significant part of what assert() is; %g is a comparatively minor
detail about how printf() works. This is obviously a judgement call, but
objectively you can see that defining the NDEBUG feature takes up almost
all of 7.2p1, which is a large fraction of the size of 7.2.1, which
describes how assert() behaves when NDEBUG isn't #defined.

As a purely practical matter, if you have a good reason for not wanting
to turn off an assert(), it's going to be a problem if someone else
who's working with your code compiles it using -DNDEBUG, because of
their own asserts. I don't thing your printf("%g") analogy covers that
issue.
I consider it implied by your use of assert() that turning it off that
way is acceptable. The issue is clear communications - not to the
compiler, but to other people maintaining the code. If it is in fact
not acceptable, I'm going to blame your use of assert() for being
misleading, not their use of -DNDEBUG.

Richard Damon

unread,
Sep 7, 2018, 2:11:09 PM9/7/18
to
I find having a debugger break-point in abort() or having an abort that
makes an appropriate core dump that can be loaded into a debugger a
useful feature.

This is of course mostly useful in the debugging environment, where such
things are available and useful. In production code, yes, you likely
want to catch the error earlier and perform cleanup.

The one key feature about assert being able to be turned off is that the
assert call must not have any needed side effects, as when you turn off
the asserts in production, those side effects go away.

Ian Collins

unread,
Sep 7, 2018, 3:28:28 PM9/7/18
to
On 08/09/18 06:10, Richard Damon wrote:
>
> I find having a debugger break-point in abort() or having an abort that
> makes an appropriate core dump that can be loaded into a debugger a
> useful feature.
>
> This is of course mostly useful in the debugging environment, where such
> things are available and useful. In production code, yes, you likely
> want to catch the error earlier and perform cleanup.
>
> The one key feature about assert being able to be turned off is that the
> assert call must not have any needed side effects, as when you turn off
> the asserts in production, those side effects go away.

I once placed a bunch of initialisation code in asserts, worked well in
testing but not so well in the target build... Pesky side effects :)

--
Ian.

Öö Tiib

unread,
Sep 8, 2018, 6:01:40 AM9/8/18
to
On Friday, 7 September 2018 15:02:21 UTC+3, Jorgen Grahn wrote:
> On Thu, 2018-09-06, james...@alumni.caltech.edu wrote:
> > On Thursday, September 6, 2018 at 4:55:10 AM UTC-4, Juha Nieminen wrote:
> >> Ian Collins <ian-...@hotmail.com> wrote:
> >> > Most but not all; sometimes we need to protect against the impossible!
> >> >
> >> > While an assertion may be user unfriendly, crashing the system with a
> >> > stack-trace and core dump is very developer friendly. Throwing an
> >> > exception looses the forensic trail to the crash.
> >>
> >> In general, use assert() for situations that indicate such a serious
> >> bug in the program that there is no recovery possible and the only
> >> viable and sane thing to do is to just terminate the program there,
> >> because it can't possibly work correctly anymore. Most useful at the
> >> development stage, of course. (Whether the assertions should be left
> >> in the final published product is another complex question.)
> >
> > One of the key features of assert() is the ability to turn it off by
> > #defining NDEBUG. If you have no intention of ever using that feature,
> > you should define your own assert-like macro that doesn't have that
> > feature.
>
> Why? I don't define my own std::printf() just because I never use the
> %g format specifier.

That was rhetorical, tongue in cheek?

> More seriously, shipping with assert() enabled may be something you
> dislike, but it doesn't violate the semantics of assert() itself.
> Unlike many other common assert usage patterns.

It is important reason of having our own "crash unless" instead of
"assert". It can't be turned off without erasing it. Therefore it
will indeed guarantee behavior. It guarantees that its arguments are
evaluated. When the assumption fails then it guarantees to report
about failure and to cause real crash instead of undefined behavior
(that it most likely guards against). Also it guarantees that code
reviewers, compilers and static analyzing tools see always actual
[[ noreturn ]] function call there and therefore can not whine that
variable might be used without initialization or pointer that might
be null is dereferenced or array might be accessed out of bounds.

Case where we really *prefer* undefined behavior to guaranteed crash
is actually ultra rare and so deserves lengthy comment why. Why?
No tongue in cheek here.


Öö Tiib

unread,
Sep 8, 2018, 6:04:32 AM9/8/18
to
On Friday, 7 September 2018 15:58:25 UTC+3, Scott Lurndal wrote:
> Juha Nieminen <nos...@thanks.invalid> writes:
> >If you are making a closed program for a limited number of platforms,
>
> *snort* mmap is portable to a very large number of platforms - there
> is only one that it is not directly portable to (but could be shimmed
> on windows).

All platforms that lack virtual memory also lack mmap.

Alf P. Steinbach

unread,
Sep 8, 2018, 11:11:18 AM9/8/18
to
On 08.09.2018 12:01, Öö Tiib wrote:
> On Friday, 7 September 2018 15:02:21 UTC+3, Jorgen Grahn wrote:
[snip]
>> More seriously, shipping with assert() enabled may be something you
>> dislike, but it doesn't violate the semantics of assert() itself.
>> Unlike many other common assert usage patterns.
>
> It is important reason of having our own "crash unless" instead of
> "assert". It can't be turned off without erasing it. Therefore it
> will indeed guarantee behavior. It guarantees that its arguments are
> evaluated. When the assumption fails then it guarantees to report
> about failure and to cause real crash instead of undefined behavior
> (that it most likely guards against). Also it guarantees that code
> reviewers, compilers and static analyzing tools see always actual
> [[ noreturn ]] function call there and therefore can not whine that
> variable might be used without initialization or pointer that might
> be null is dereferenced or array might be accessed out of bounds.

Hm, [[noreturn]] for a macro that normally does return?


auto foo( int x )
-> std::string
{
CRASH_UNLESS( x == 42 );
// This function always has UB except when x is 42.
// Diagnostic silenced by the [[noreturn]] nature of CRASH_UNLESS
}


> Case where we really *prefer* undefined behavior to guaranteed crash
> is actually ultra rare and so deserves lengthy comment why. Why?
> No tongue in cheek here.

I like the idea of well-defined behavior.


Cheers!,

- Alf

Paavo Helde

unread,
Sep 8, 2018, 12:22:05 PM9/8/18
to
On 6.09.2018 15:54, james...@alumni.caltech.edu wrote:
> For instance, if assert(a<b) would
> be triggered, I'd want information about the current values of a and b.

In an interpreted language supporting such assert would be easy. If an
assert fails, the interpreter will take the assert expression, parse it
into a syntax tree, evaluate each tree node and output the values to the
log file or include them in the error message as appropriate.

In principle one should be able to do the same in C++ as the asserted
expression is known at compile time; the compiler could generate code
for calculating the subexpressions and outputting their values.

Alas, I'm afraid C++ introspection features are not yet advanced enough
that this task could be done in standard C++. Maybe there is some
development happening or planned along these lines?

Öö Tiib

unread,
Sep 8, 2018, 2:53:31 PM9/8/18
to
On Saturday, 8 September 2018 18:11:18 UTC+3, Alf P. Steinbach wrote:
> On 08.09.2018 12:01, Öö Tiib wrote:
> > On Friday, 7 September 2018 15:02:21 UTC+3, Jorgen Grahn wrote:
> [snip]
> >> More seriously, shipping with assert() enabled may be something you
> >> dislike, but it doesn't violate the semantics of assert() itself.
> >> Unlike many other common assert usage patterns.
> >
> > It is important reason of having our own "crash unless" instead of
> > "assert". It can't be turned off without erasing it. Therefore it
> > will indeed guarantee behavior. It guarantees that its arguments are
> > evaluated. When the assumption fails then it guarantees to report
> > about failure and to cause real crash instead of undefined behavior
> > (that it most likely guards against). Also it guarantees that code
> > reviewers, compilers and static analyzing tools see always actual
> > [[ noreturn ]] function call there and therefore can not whine that
> > variable might be used without initialization or pointer that might
> > be null is dereferenced or array might be accessed out of bounds.
>
> Hm, [[noreturn]] for a macro that normally does return?

Sorry for being ambiguous, I meant that CRASH_UNLESS to be usually a
macro that expands to something like that:

#define CRASH_UNLESS(EX) (void)((EX) || (report_and_crash(#EX, __FILE__ \
, __LINE__),false))

It is a macro because of __FILE__ and __LINE__ and to achieve
that [[noreturn]] function report_and_crash is called only when the
expression EX evaluates to false.

Jorgen Grahn

unread,
Sep 11, 2018, 6:26:24 PM9/11/18
to
I think I might have inadvertently stepped into an old debate about
assert, and don't want to enter it permanently. Just to clarify my
view a bit: I believe that if it matters whether I disable assert(),
I have a bug.

Jorgen Grahn

unread,
Sep 11, 2018, 6:27:54 PM9/11/18
to
On Sat, 2018-09-08, Öö Tiib wrote:
> On Friday, 7 September 2018 15:02:21 UTC+3, Jorgen Grahn wrote:
>> On Thu, 2018-09-06, james...@alumni.caltech.edu wrote:
>> > On Thursday, September 6, 2018 at 4:55:10 AM UTC-4, Juha Nieminen wrote:
>> >> Ian Collins <ian-...@hotmail.com> wrote:
>> >> > Most but not all; sometimes we need to protect against the impossible!
>> >> >
>> >> > While an assertion may be user unfriendly, crashing the system with a
>> >> > stack-trace and core dump is very developer friendly. Throwing an
>> >> > exception looses the forensic trail to the crash.
>> >>
>> >> In general, use assert() for situations that indicate such a serious
>> >> bug in the program that there is no recovery possible and the only
>> >> viable and sane thing to do is to just terminate the program there,
>> >> because it can't possibly work correctly anymore. Most useful at the
>> >> development stage, of course. (Whether the assertions should be left
>> >> in the final published product is another complex question.)
>> >
>> > One of the key features of assert() is the ability to turn it off by
>> > #defining NDEBUG. If you have no intention of ever using that feature,
>> > you should define your own assert-like macro that doesn't have that
>> > feature.
>>
>> Why? I don't define my own std::printf() just because I never use the
>> %g format specifier.
>
> That was rhetorical, tongue in cheek?

No; I genuinely didn't understand.

Jorgen Grahn

unread,
Sep 11, 2018, 6:37:06 PM9/11/18
to
On Fri, 2018-09-07, Richard Damon wrote:
...
> I find having a debugger break-point in abort() or having an abort that
> makes an appropriate core dump that can be loaded into a debugger a
> useful feature.
>
> This is of course mostly useful in the debugging environment, where such
> things are available and useful. In production code, yes, you likely
> want to catch the error earlier and perform cleanup.

Why the "of course"? Faults in live and other non-debugging
environments are not exactly unheard of. I don't want the evidence
cleaned away in such a scenario. (Although it may, for some programs,
be even more important to save valuable data or similar.)

james...@alumni.caltech.edu

unread,
Sep 11, 2018, 6:48:47 PM9/11/18
to
On Tuesday, September 11, 2018 at 6:26:24 PM UTC-4, Jorgen Grahn wrote:
> On Fri, 2018-09-07, james...@alumni.caltech.edu wrote:
...
> > I consider the fact that it can be turned off by #defining NDEBUG to be
> > a very significant part of what assert() is; %g is a comparatively minor
> > detail about how printf() works. This is obviously a judgement call, but
> > objectively you can see that defining the NDEBUG feature takes up almost
> > all of 7.2p1, which is a large fraction of the size of 7.2.1, which
> > describes how assert() behaves when NDEBUG isn't #defined.
> >
> > As a purely practical matter, if you have a good reason for not wanting
> > to turn off an assert(), it's going to be a problem if someone else
> > who's working with your code compiles it using -DNDEBUG, because of
> > their own asserts. I don't thing your printf("%g") analogy covers that
> > issue.
> > I consider it implied by your use of assert() that turning it off that
> > way is acceptable. The issue is clear communications - not to the
> > compiler, but to other people maintaining the code. If it is in fact
> > not acceptable, I'm going to blame your use of assert() for being
> > misleading, not their use of -DNDEBUG.
>
> I think I might have inadvertently stepped into an old debate about
> assert, and don't want to enter it permanently. Just to clarify my
> view a bit: I believe that if it matters whether I disable assert(),
> I have a bug.

Agreed. Disabling assert() is something you should only do when you have
no more than an acceptable amount of uncertainty about whether there are
any uncaught bugs that might be caught by the asserts. You can never
completely eliminate that risk, but that risk can, depending upon
circumstances, be arbitrarily small. The key point is that risk might be
small enough that some other issue is sufficient to justify taking that
risk.
The usual justification for disabling it is that the test it performs is
too expensive to put in the delivered code - it can only be a single
expression, but even in C, that could involve a call to an arbitrarily
expensive function call. In C++, operator overloads can make code very
expensive to execute which would seem completely innocuous if
interpreted as C code.
Another justification is that the text of the assert message could give
the user information about the program that the developer doesn't want
the user to have.

As I said, I don't like assert(), so I'm giving advice that applies
solely to people other than myself - feel free to judge the value of my
advice accordingly.

Öö Tiib

unread,
Sep 11, 2018, 6:58:54 PM9/11/18
to
Because someone stupid turns it off to save 2% of performance or 10% of
binary size. Then someone smart discovers a way how to exploit it.
After that there is potentially a hard to discover full backdoor instead
of guaranteed easy to patch denial-of-service vector.

Öö Tiib

unread,
Sep 11, 2018, 7:25:19 PM9/11/18
to
I believe that when C++ programs are written then either those are
useless or these contain bugs or someone has found a trick how to
hire omnipotent beings as C++ programmers. ;)

Robert Wessel

unread,
Sep 12, 2018, 10:47:23 AM9/12/18
to
On Sat, 8 Sep 2018 03:04:23 -0700 (PDT), 嘱 Tiib <oot...@hot.ee>
wrote:
Without paging hardware, it would indeed be hard to implement mmap (at
least fully), but actually implementing virtual memory (with the same
paging hardware) is not quite the same thing (although if you
implement one, you've done a fair bit of the work needed for the
other).

Most android platforms, for example, support mmap, but don't implement
virtual memory.

Öö Tiib

unread,
Sep 12, 2018, 1:48:06 PM9/12/18
to
On Wednesday, 12 September 2018 17:47:23 UTC+3, robert...@yahoo.com wrote:
> On Sat, 8 Sep 2018 03:04:23 -0700 (PDT), Öö Tiib <oot...@hot.ee>
Android definitely uses virtual memory, only swap space is not enabled
in its kernel. Twelve minute lecture about it:
https://www.androidauthority.com/what-is-virtual-memory-gary-explains-747960/

0 new messages