Thursday, August 22, 2019

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

Tim Rentsch <tr.17687@z991.linuxsc.com>: Aug 22 10:28AM -0700


>> As far as the Standard is concerned these two functions are
>> semantically equivalent.
 
> If resource limits are not exceeded.
 
The semantics of a program is what is specified to happen in the
abstract machine. Resource limits come into play only when a
program is run on an actual machine; they have no bearing on
program semantics.
 
 
> Yes.
 
>> They have exactly the same implications for observable behavior.
 
> No.
 
Please outline a scenario in the abstract machine when the two
functions have different observable behavior.
 
>> If one has undefined behavior then so does the other.
 
> No.
 
Please outline a scenario in the abstract machine when one of the
two functions unconditionally has undefined behavior and the other
does not.
 
 
>> If one has a risk of undefined behavior then so does the other.
 
> Repeating that claim doesn't make it less incorrect.
 
It isn't the same claim. The first is about undefined behavior
that must occur, the second is about undefined behavior that
may occur but doesn't have to. (see next)
 
> I'm pretty sure that you inadvertently repeated it because it was
> orbiting in your mind, the key thing to communicate.
 
No, I made a separate point to address your individual idea of
what "undefined behavior" means. (As a side comment, other
people disagree with your view - see this SO question:
 
https://stackoverflow.com/questions/56811284/
does-this-program-with-bounded-recursion-have-undefined-behavior
 
in particular the most highly voted answer.)
 
> But it's trivially false: for a just some orders of magnitude
> larger array size I can arrange to consistently crash the
> recursive function, while the iterative one will be fine.
 
You point out later that /any/ function call can run out stack
space and so (under your view) has a risk of undefined behavior.
So my statement is trivially true.
 
 
>> implementation may choose to compile an iterative definition into
>> recursive object code
 
> No, absolutely not.
 
Don't be silly, of course it can. The C and C++ standards don't say
anything about how a program is compiled except that the compiled
code has to match the observable behavior of the abstract machine.
In fact, very much the opposite: program semantics is defined in
terms of behavior in the abstract machine, and "conforming
implementations are required to emulate (only) the observable
behavior of the abstract machine". Observable behavior does not
include stack depth. Both the C and the C++ standard explicitly
give unbounded latitude as long as the observable behavior
requirement is met.
 
 
>> , as well as vice versa.
 
> Yes, it /can/ transform a recursive one to an iterative one that
> uses less resources.
 
I think you are confused about what "observable behavior" means.
Observable behavior does not depend on what resources are
available.
 
>> also say the C++ standard gives you no guarantee about whether the
>> iterative function might result in undefined behavior.
 
> That would follow if your premises were true, but they aren't.
 
You claim they aren't. Please support that claim by providing
one of the example scenarios I asked for above.
 
> run a risk, that swimming and flying are somehow on equal terms,
> ignores the important real world aspects and focus on a wholly
> unreasonable, dangerous academic simplification. As I see it.
 
Practical considerations are a separate concern, which I may take
up in a separate response.
 
> to rewrite an iterative function as recursive, then that /would/
> have been that kind of in-effect-sabotage, and then I /would/ have
> used derogatory words. ;-)
 
The current standards, back to and including the original C89
standard, deliberately grant sufficient latitude to make arbitrarily
poor implementation choices as long as the observable behavior
requirement is met. I'm sure this was a conscious decision, and
not either an academic one or one divorced from reality. You are
very much swimming upstream here: do you really want to say you are
smarter than all the people who have participated in the C and C++
working groups to standardize these languages? I hope you will
understand if I view these last remarks with a fair amount of
skepticism.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 22 07:50PM +0200

On 22.08.2019 19:28, Tim Rentsch wrote:
> very much swimming upstream here: do you really want to say you are
> smarter than all the people who have participated in the C and C++
> working groups to standardize these languages?
 
There are 3 main things wrong with that statement:
 
* The idea that I'm arguing a view at odds with the standard. I'm not.
Check how many in this group agree with your view of UB: that's 0.
 
* The idea that /if/ one believes the standard is sub-optimal or wrong,
one must believe that one is smarter than all the people blah blah. If
that were the case then all those non-committee members who have filed
Defect Reports against the standard, must be megalomaniacs who think
they're very very smart. That's just not so.
 
* It's a purely social argument.
 
 
> I hope you will
> understand if I view these last remarks with a fair amount of
> skepticism.
 
[Hark.]
 
I may address the rest of your posting later, trying to give the
examples etc. you ask for, because I feel you mean this seriously.
 
And I don't think you think you're smarter than everybody else in this
group just for holding an opinion on UB that nobody else here shares.
 
I think you're simply convinced that you're right, that your
distinctions are meaningful, and somehow my and others' arguments have
failed to move your conviction. Which I think means we're not good
enough at presenting our view. Not, that we're wrong. ;-)
 
 
Cheers!,
 
- Alf (fairly intelligent but at least now not at Mensa level :) )
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 22 03:38AM +0200

On 21.08.2019 21:41, Keith Thompson wrote:
 
> By accepting identifiers with "$" without a diagnostic in what is
> intended to be a conforming mode, g++ is violating the requirements of
> the C++ standard. If you disagree, what exactly is your argument?
 
The above responds to what was a coherent /reductio ad absurdum/
argument, now lost in refocusing on and possibly misinterpreting one of
the shattered pieces of it.
 
As pointed out by you up-thread it's not the case that accepting the `$`
requires a diagnostic in all versions of the standard. g++ is simply not
fully up to date regarding C++17 in this respect. But then few
compilers, if any, are standard-conforming by default: one needs to
cajole them into conformance by applying the relevant set of options.
 
 
> "diagnostic" in a way that's consistent with that. No implementation
> does so or is likely to do so in the future.
 
> I thought your argument was based on "common sense".
 
Yep.
 
 
> to allow for that). Which is why, in my opinion, the standard *should*
> allow compilers to accept $ in identifiers.
 
> [...]
 
Yes, I should have written MPE/IV, the OS we used on the HP3000. Sorry.
 
It's possible that all this is tied to the attempt to remove `$` in
ASCII, as I recall instigated by Russia or France, a political thing. I
mean, tied by the baffling decision to not include `$` in the C++ basic
execution character set.
 
For the new ASCII that I don't remember the name of, we got the (hark)
universal currency symbol `¤` as a replacement for `$`. Nobody uses
that. It's meaningless except as a political statement, but it's there
on my keyboard, taking up one key combination.
 
 
Cheers!,
 
- Alf
Keith Thompson <kst-u@mib.org>: Aug 21 07:24PM -0700

> On 21.08.2019 21:41, Keith Thompson wrote:
[...]
 
> The above responds to what was a coherent /reductio ad absurdum/
> argument, now lost in refocusing on and possibly misinterpreting one of
> the shattered pieces of it.
 
I still can't make any sense of what you've written so far in this
thread. Perhaps I'll stop trying.
 
> fully up to date regarding C++17 in this respect. But then few
> compilers, if any, are standard-conforming by default: one needs to
> cajole them into conformance by applying the relevant set of options.
 
As I said, I did apply the relevant set of options.
 
C++17 does not permit '$' in identifiers, and requires a diagnostic
for any program that attempts to use a '$' in an identifier.
Earlier editions of the standard do permit implementations to support
'$' in identifiers. gcc's lack of a diagnostic in conforming mode
"gcc -std=c++17 -Wpedantic" makes it non-conforming. If you agree
with that, I don't know what we're arguing about. If you don't,
I have yet to see an explanation.
 
I've also suggested that the committee probably did not intend to
make a significant change in this area.
 
[...]
 
> ASCII, as I recall instigated by Russia or France, a political thing. I
> mean, tied by the baffling decision to not include `$` in the C++ basic
> execution character set.
 
I've never heard of any attempt to remove '$' from ASCII, which I
believe has not changed since 1967. Do you have a citation for that?
 
'$' is not in the source or execution basic character set, a decision
that was made a long time ago. Apparently '$' is not supported in
all versions of EBCDIC, or at least doesn't have a consistent code
(see the Wikipedia article). And there are no tokens in C or C++
that required $ (or @ or `, the only three printable ASCII characters
not in the C or C++ basic character set).
 
> universal currency symbol `¤` as a replacement for `$`. Nobody uses
> that. It's meaningless except as a political statement, but it's there
> on my keyboard, taking up one key combination.
 
There is no "new ASCII". ASCII is a 7-bit character set. '¤' is part
of Unicode (and Latin-1). Unicode calls it "CURRENCY SIGN". It's not a
replacement for '$' (DOLLAR SIGN), which still exists in ASCII, Latin-1,
and Unicode. (DOLLAR SIGN is 0x24. CURRENCY SIGN is 0xA4.) If there's
a political issue, it's not one that interests me unless it's relevant
to C++.
 
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 21 11:21PM -0400

On 8/21/19 10:24 PM, Keith Thompson wrote:
> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
...
> believe has not changed since 1967. Do you have a citation for that?
 
> '$' is not in the source or execution basic character set, a decision
> that was made a long time ago.
 
To be more precise, that decision predates the C++ standard, which
inherited it from the C standard. It had already been made by the time
C89 was approved. K&R did not allow '$' in identifiers, and didn't use
it anywhere in the C grammar, but didn't say anything about whether an
implementation was required to accept such characters if they appeared
in header names, comments, character constants, or string literals. The
decision to not include $ in either the source or execution basic
character sets was presumably made at the same time that it was decided
that the standard should specify those sets.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 22 06:01AM +0200

On 22.08.2019 04:24, Keith Thompson wrote:
>> execution character set.
 
> I've never heard of any attempt to remove '$' from ASCII, which I
> believe has not changed since 1967. Do you have a citation for that?
 
Wikipedia's article on `¤` mentions that the replacement was formally
proposed by Italy.
 
It cites an article on the web, written by an unknown *nix administrator
in the 1990s, but with easily checkable facts:
 
<url: http://czyborra.com/charsets/iso646.html>
[quote]
ASCII and its national variants were declared international standard ISO
646 in 1972. Back then, the socialist countries managed to substitute
the international currency sign ¤ for ASCII's capitalist dollar sign $
in the the first international reference version ISO-646-IRV but this
was revised in 1991 and now ISO-646-IRV is a synonym for ISO-646-US or
US-ASCII as it is used in the core Internet protocols.
[/quote]
 
I guess this is where I remembered Russia from.
 
Or some other source discussing the same history. It was all political.
 
The 1991 6th edition of that standard confirms in its annex C the above
claim that the new ASCII, ISO-646 (note: the codes of Unicode are
ISO-10646), "was revised" back to its former `$`-glory:
 
[quote]
3) In the G0 set of the IRV the character DOLLAR SIGN replaces the
character CURRENCY SIGN in position 2/4.
Otherwise this G0 set is unchanged.
[quote]
 
 
>> that. It's meaningless except as a political statement, but it's there
>> on my keyboard, taking up one key combination.
 
> There is no "new ASCII".
 
I'm sorry, that's just wrong, although that statement is literally true
by using the word "is" instead of "never was".
 
 
> of Unicode (and Latin-1). Unicode calls it "CURRENCY SIGN". It's not a
> replacement for '$' (DOLLAR SIGN), which still exists in ASCII, Latin-1,
> and Unicode. (DOLLAR SIGN is 0x24. CURRENCY SIGN is 0xA4.)
 
Yes, it's back in place. Since 1991. Apparently the international
currency sign idiocy was adopted in 1972, but even Wikipedia contradicts
itself on this matter, so I'm not 100% sure when it started.
 
 
> If there's
> a political issue, it's not one that interests me unless it's relevant
> to C++.
 
I think it's quite possibly relevant to the original decision to not
include `$`.
 
A mistaken political correctness stance where `$` was seen as just too
Western-ish, as a kind of discrimination.
 
 
Cheers!,
 
- Alf
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 22 12:26AM -0400

On 8/22/19 12:01 AM, Alf P. Steinbach wrote:
> On 22.08.2019 04:24, Keith Thompson wrote:
>> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
...
 
>> There is no "new ASCII".
 
> I'm sorry, that's just wrong, although that statement is literally true
> by using the word "is" instead of "never was".
 
ASCII was first standardized as ASA X3.4-1963, and was revised in 1965,
1967, 1968, 1977, and 6 different versions came out in 1986
<https://en.wikipedia.org/wiki/ASCII#History>. So you're right - there
has been a "new ASCII" - a total of 10 of them, in fact. However, that
was all a long time ago, and every one of those versions included $.
What you're referring to is an early version of ISO/IEC 646, which was
based on ASCII and was ASCII's successor, but is not, itself, ASCII.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 22 07:54AM +0200

On 22.08.2019 06:26, James Kuyper wrote:
> 1967, 1968, 1977, and 6 different versions came out in 1986
> <https://en.wikipedia.org/wiki/ASCII#History>. So you're right - there
> has been a "new ASCII" - a total of 10 of them, in fact.
 
You're talking about the US national variant of ISO-646.
 
That's a meaningless interpretation of what I wrote.
 
What the fuck could I have meant when I wrote "the new ASCII that I
don't remember the name of"? Could it be that I didn't remember the name
ASCII that I mentioned in that very sentence? Yes, that must surely have
been what I meant.
 
But wait, that's already clarified up-thread, in the parts you snipped:
it was ISO 646, the international, ISO version of ASCII.
 
Removing significant context and introducing one's own apparent context
instead, is not like debate or clarification.
 
That's instead a common trolling technique.
 
 
> However, that
> was all a long time ago, and every one of those versions included $.
 
Yes, and as you well know that's irrelevant to anything in this thread.
 
Perhaps there were reasons that caused you to not see as relevant the
stuff that you snipped, but a debate or clarification can't be your goal
because you can't be unaware of the facts: you're presenting some.
 
The stuff that you snipped included reference to ISO 646, the
international version of ASCII, which from (apparently) 1972 to
(verified) 1991 had the `$` replaced with an unusable international
currency symbol `¤`.
 
 
> What you're referring to is an early version of ISO/IEC 646, which was
> based on ASCII and was ASCII's successor, but is not, itself, ASCII.
 
Yes, and again, as you well know that's irrelevant to anything.
 
Not sure if I should plink you, you're not usually trolling this way,
 
- Alf
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 22 09:08AM -0400

On 8/22/19 1:54 AM, Alf P. Steinbach wrote:
>> <https://en.wikipedia.org/wiki/ASCII#History>. So you're right - there
>> has been a "new ASCII" - a total of 10 of them, in fact.
 
> You're talking about the US national variant of ISO-646.
 
No, ASCII and ISO-646 have been developed cooperatively, and there is a
US national variant of ISO-646 that is identical in content to one of
the versions of ASCII, but that doesn't make ASCII a national variant of
ISO-646.
 
 
> What the fuck could I have meant when I wrote "the new ASCII that I
> don't remember the name of"? Could it be that I didn't remember the name
> ASCII that I mentioned in that very sentence?
 
No, each version of ASCII had it's own name, such as
ASA X3/4-1963 and ANSI-INCITS 4-1986. It was quite clear, since you
describe it as having replaced the dollar sign with the currency symbol,
that the only thing you could have been referring to was ISO 646 IRV.
However, given your usual sloppiness of thought, I assumed that you
actually meant what you said - that you were under the impression that
ISO 646 IRV was the name of a "... new [version of] ASCII ..." but that
you couldn't remember the name of that particular version.
 
I'm glad to hear that this was only sloppy wording on your part, and
that you're actually aware that it's a different standard, issued by an
international standards organization, rather than a merely national one.
scott@slp53.sl.home (Scott Lurndal): Aug 22 01:17PM

>> allow compilers to accept $ in identifiers.
 
>> [...]
 
>Yes, I should have written MPE/IV, the OS we used on the HP3000. Sorry.
 
Which HP3000 language allowed '$' in identifiers? On most HP3000
compilers the $ was used in column 1 to introduce compiler control
commands, for example in SPL/3000:
 
$TITLE "SON OF OVERLORD (SOO)"
$CONTROL USLINIT,NOWARN,MAP,CODE
$CONTROL SEGMENT=SOO
BEGIN ...
 
SPL did allow apostrophes in identifiers:
 
INTEGER PRIORITY, XDS'SUB, MAXPCB', MODE;
 
The engineers that designed the HP3000 were mostly ex-burroughs
engineers, which is where the use of $ as a compiler control
originated.
 
 
>It's possible that all this is tied to the attempt to remove `$` in
>ASCII, as I recall instigated by Russia or France, a political thing.
 
C'est what?
 
> I
>mean, tied by the baffling decision to not include `$` in the C++ basic
>execution character set.
 
Maybe because the '$' symbol was often substited with a national
symbol (e.g. the british pound symbol); it wasn't a fixed glyph
worldwide.
David Brown <david.brown@hesbynett.no>: Aug 22 04:07PM +0200

On 22/08/2019 15:17, Scott Lurndal wrote:
 
> Maybe because the '$' symbol was often substited with a national
> symbol (e.g. the british pound symbol); it wasn't a fixed glyph
> worldwide.
 
It was the # symbol that was replaced by £ in the GB version of ISO-646,
and on British keyboards. The $ sign remained. (Also ~ was replaced by
an overbar ‾, but I've no idea why.)
 
The $ symbol was kept in most, but not all, ISO-646 character sets. It
was more common to replace characters like # { } [ ] | and ~ , all of
which are still there in C (but have trigraphs).
 
On a related topic, what is the rationale behind the choice of
characters allowed in universal character identifiers? There seems to
be a vague attempt to allow "letters" but not "symbols". Surely
allowing symbols like ¤ £ and § would be ideal for the kind of thing Alf
has in his library - characters that would not conflict with anything
else, stand out clearly, and can by typed easily on many keyboard
layouts (even with Windows).
 
Perhaps € would be a good choice - it is in the list of allowed Unicode
identifier characters.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 22 07:37PM +0200

On 22.08.2019 15:08, James Kuyper wrote:
>> ASCII that I mentioned in that very sentence?
 
> No, each version of ASCII had it's own name, such as
> ASA X3/4-1963 and ANSI-INCITS 4-1986.
 
"It's" is spelled "its".
 
That's pretty sloppy spelling from you.
 
 
> [snip]
> However, given your usual sloppiness of thought,
 
You don't say.
 
 
> actually meant what you said - that you were under the impression that
> ISO 646 IRV was the name of a "... new [version of] ASCII ..." but that
> you couldn't remember the name of that particular version.
 
That explanation does not address the precision of snipping all mention
of ISO 646 in the text your replied to, which appeared to be designed to
mislead.
 
Not addressing your snipping of significant context is a sloppiness of
deception, an art that you don't quite master.
 
 
> I'm glad to hear that this was only sloppy wording on your part,
 
And that's associative, like an associative mind. It's true that the
wording was intentionally imprecise. It communicated exactly what I
meant to say, notwithstanding your unconvincing attempt to put it in a
different context, remove all mention of what it meant, and so on.
 
 
> and
> that you're actually aware that it's a different standard, issued by an
> international standards organization, rather than a merely national one.
 
You didn't learn that now.
 
You snipped those parts of the quoted text, remember.
 
To do that snipping you had to recognize what it was about, which you
now pretend to have understood, which means you are now conveying an
incorrect impression that you /know/ is incorrect, which there is a word
for.
 
 
Cheers!,
 
- Alf
Szyk Cech <szykcech@spoko.pl>: Aug 22 06:18PM +0200

Hello!
 
I want follow advises of great book: "Testen in Scrum-Projekten" by Tilo
Linz. One of his advises which I consider easy to make is use static
code analyser to check if programmers respect coding rules.
 
I am looking for C++ code analyser but I am interested with such tool
for Java Script or Bash also.
 
I found great wiki page with list of most popular static code analysers:
 
https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis
 
but I have no time to try all of them.
So maybe you have some experience with those tools if so:
Please answer me to question:
 
What is easiest to use static C++ code analyser?
 
Thak you in advance and best regards!
Szyk Cech
JiiPee <no@notvalid.com>: Aug 22 03:25PM +0100

On 21/08/2019 20:52, Öö Tiib wrote:
> Snipping possible misrepresentation of Herb Sutter and
> CppCoreGuidelines of isocpp.
 
 
Sutter says like: "Always make all data members private. The only
exception is c-style struct where all members are public"
 
So he was against putting some private and some public. And he proves
his point.
 
So according to him if Person class has some functions (like increasing
the age automatically) then the age itself should be private and if its
value is needed we need a getter.
"Öö Tiib" <ootiib@hot.ee>: Aug 22 09:06AM -0700

On Thursday, 22 August 2019 17:25:24 UTC+3, JiiPee wrote:
> > CppCoreGuidelines of isocpp.
 
> Sutter says like: "Always make all data members private. The only
> exception is c-style struct where all members are public"
 
CppCoreGuidelines at
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get>
does not conflict with it just suggest to prefer that c-style struct
to all trivial setters and getters. That is why your claim seemed
misrepresentation.
 
> So he was against putting some private and some public. And he proves
> his point.
 
Your OP did not discuss putting some data members private and
some public, both are against it:
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c134-ensure-all-non-const-data-members-have-the-same-access-level>
 
> So according to him if Person class has some functions (like increasing
> the age automatically) then the age itself should be private and if its
> value is needed we need a getter.
 
What you seemingly asked in your OP was if to have trivial setters
and getters or to have c-style struct. "Getter" is red herring
since you don't need one with c-style struct.
stdcerr <ron.eggler@gmail.com>: Aug 21 08:12PM -0700

On Tuesday, August 20, 2019 at 5:07:52 PM UTC-7, Sam wrote:
> > foo(const QSettings *set=0, const QString s="") :
> > name(s),settings(set){}
 
> You must be using an obsolete C++ book.
 
I used the really thick book called Internet only and it didn't say that it's out-dated syntax, Thanks for correcting this, though!
Modern C++ uses uniform

> initialization syntax, which would be:
 
> foo(const QSettings *set=0, const QString s="") : name{s},settings{set}{}
 
That looks more like the Lambda syntax from >=C++11
 
> Basically {} instead of (). This resolves some syntax ambiguities in other
> situations (not this particular one, but others, and it's better to remain
> consistent).
 
100% Agreed! Thanks for the correction!
 
> > ^
> > Makefile:471: recipe for target 'foo.o' failed
> > make: *** [foo.o] Error 1
 
I'm not sure why the compiler doesn't like is, why can't the instance of foo not be a pointer? To get past this, I changed it to look like:
foo inst = foo(sttngs, QString("quux"));
inst.qux();
 
 
 
> const QSettings * const settings;
 
> Which is a const class member named "settings" which is a pointer to a const
> QSettings object.
 
The latter one is what I went with as it seems to be more consistent with my requirement. So my constructor prototype now looks like:
foo(const QSettings* const set=nullptr, const QString s="") : name{s},settings{set}{}
 
which works fine but now the compiler complains:
 
foo.cpp: In member function 'void foo::qux()':
foo.cpp:18:30: error: passing 'const QSettings' as 'this' argument discards qualifiers [-fpermissive]
settings->beginGroup(name);
^
In file included from /usr/include/x86_64-linux-gnu/qt5/QtCore/QSettings:1:0,
from foo.cpp:2:
/usr/include/x86_64-linux-gnu/qt5/QtCore/qsettings.h:130:10: note: in call to 'void QSettings::beginGroup(const QString&)'
void beginGroup(const QString &prefix);
^
foo.cpp:22:24: error: passing 'const QSettings' as 'this' argument discards qualifiers [-fpermissive]
settings->endGroup();
^
In file included from /usr/include/x86_64-linux-gnu/qt5/QtCore/QSettings:1:0,
from foo.cpp:2:
/usr/include/x86_64-linux-gnu/qt5/QtCore/qsettings.h:131:10: note: in call to 'void QSettings::endGroup()'
void endGroup();
^
Makefile:471: recipe for target 'foo.o' failed
make: *** [foo.o] Error 1
 
Does this mean beginGroup() and endGroup() cannot be invoked on a const QSettings pointer ?
 
qux() hasn't changed and still looks like:
 
void foo::qux(void) {
QString name = nme_get();
settings->beginGroup(name);
/*
* ...
*/
settings->endGroup();
}
and nme_get()
QString nme_get() {return name;}
 
in order to address the above error, I tried:
void foo::qux(void) {
QSettings *test = settings;
QString name = nme_get();
test->beginGroup(name);
/*
* ...
*/
test->endGroup();
}
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 21 11:52PM -0400

On 8/21/19 11:12 PM, stdcerr wrote:
>>> public:
>>> foo(const QSettings *set=0, const QString s="") :
>>> name(s),settings(set){}
...
>>> Makefile:471: recipe for target 'foo.o' failed
>>> make: *** [foo.o] Error 1
 
> I'm not sure why the compiler doesn't like is, why can't the instance of foo not be a pointer? ...
 
An instance of foo has class type. An class type is, by definition, not
a pointer type. You could have defined an implicit conversion from an
object of type foo to a pointer to a foo object, but that's almost
certainly not what you wanted.
 
> ... To get past this, I changed it to look like:
> foo inst = foo(sttngs, QString("quux"));
 
Note: the line above is equivalent to
foo inst(sttngs, QString("quux"));
 
 
>> const QSettings * const settings;
 
>> Which is a const class member named "settings" which is a pointer to a const
>> QSettings object.
 
Let me review your options:
 
const QSettings * const settings;
Declares settings to be a pointer, which cannot be changed, to a
QSettings object that cannot be changed through that pointer.
 
QSettings * const settings;
Declares settings to be a pointer, which cannot be changed, to a
QSettings object that can be changed through that pointer.
 
const QSettings * settings;
Declares settings to be a pointer, which can be changed, to a QSettings
object that cannot be changed through that pointer.
 
QSettings * settings;
Declares settings to be a pointer, which can be changed, to a QSettings
object that can be changed through that pointer.
 
So, which of these declarations is most appropriate for your
application? Your code never changes the value of settings once it has
been initialized, so declaring settings itself const makes sense.
 
However:
 
...
> foo.cpp: In member function 'void foo::qux()':
> foo.cpp:18:30: error: passing 'const QSettings' as 'this' argument discards qualifiers [-fpermissive]
> settings->beginGroup(name);
 
<https://doc.qt.io/qt-5/qsettings.html#beginGroup> does not include the
'const' keyword in the declaration for beginGroup(), which is easy to
understand, since it describes the behavior as "Appends prefix to the
current group.", an action that requires modification of the QSettings
object.
 
Therefore, since you call settings->beginGroup(), it does NOT make sense
to declare "settings" as a pointer that cannot be used to modify the
object it points at. What you want is
 
QSetting * const settings;
 
> Does this mean beginGroup() and endGroup() cannot be invoked on a const QSettings pointer ?
 
Yes.
stdcerr <ron.eggler@gmail.com>: Aug 21 08:55PM -0700

On Tuesday, August 20, 2019 at 5:07:52 PM UTC-7, Sam wrote:
> > foo(const QSettings *set=0, const QString s="") :
> > name(s),settings(set){}
 
> You must be using an obsolete C++ book.
 
I'm mostly using the Internet to find out things now, I've been writing C for many years and know a little about C++(obviously not much/enough) - any good book you would recommend?
 
Modern C++ uses uniform
 
> Basically {} instead of (). This resolves some syntax ambiguities in other
> situations (not this particular one, but others, and it's better to remain
> consistent).
 
Okay, looks a bit like Lambda in C++11...
Yes, I'm all for consistency, too! Thanks!
> > 'QSettings*'"
 
> Because your parameter to the constructor is a 'const QSettings *', and your
> const class member is a pointer to a non-const QSettings.
 
DUH! Yep, obviously needs to be the same!
 
 
> const QSettings * const settings;
 
> Which is a const class member named "settings" which is a pointer to a const
> QSettings object.
 
Okay, I guess I want a const pointer to a const Object, hence I'll go with:
 
const QSettings * const settings;
 
But I still have issues, my code now looks like:
 
class foo {
Q_OBJECT
public:
foo(const QSettings* const set=nullptr, const QString s="") : name{s},settings{set}{}
QString nme_get() {return name;}
void qux(void);

private:
const QString name;
const QSettings * const settings;
};
 
void foo::qux(void) {
QSettings *test = settings;
QString name = nme_get();
test->beginGroup(name);
/*
* ...
*/
test->endGroup();
}
 
 
int main (void) {

const QSettings *sttngs = new QSettings(QSettings::NativeFormat,QSettings::UserScope,"GNU","scaper",nullptr
);

foo inst = foo(sttngs, QString("quux"));
inst.qux();

return 0;
}
 
but g++ still tells me:
foo.cpp: In member function 'void foo::qux()':
foo.cpp:17:23: error: invalid conversion from 'const QSettings*' to 'QSettings*' [-fpermissive]
QSettings *test = settings;
^
Makefile:471: recipe for target 'foo.o' failed
make: *** [foo.o] Error 1
Sam <sam@email-scan.com>: Aug 22 08:40AM -0400

stdcerr writes:
 
 
> I'm mostly using the Internet to find out things now, I've been writing C
> for many years and know a little about C++(obviously not much/enough) - any
> good book you would recommend?
 
There's a good list here:
 
https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list
 
> ^
> Makefile:471: recipe for target 'foo.o' failed
> make: *** [foo.o] Error 1
 
It is true that C++ compilers have a rich reputation for incomprehensible,
undecipherable error messages, but this is not one of them, it's as clear as
it can be.
 
Of course, you do need to already understand some C++ fundamentals, such as
what it means to be a const, and that a pointer to const cannot be converted
to a pointer to a non-const object, which is what the error message states.
 
settings is a "const QSettings *", a pointer to a constant QSettings object.
You are trying to assign it to a pointer to "QSettings *". That's it. No big
mystery. Verbotten. Nyet. Nada. No way. Nein. You /can/ assign a "QSetting
*" to a "const QSetting *", basically promising to never modify anything
that the "const QSetting *" points to. But once you made that promise it's a
one way street. It's true that you might still have the original "QSettings
*" somewhere. But as far as the promise made about the new "const QSettings
*", it is etched in stone, and irrevocable. So that means that you can't
make a "QSettings *" out of it, again.
 
Perhaps you want to grab one of those C++ books, which should explain all of
this, and all the rest of your compilation errors will suddenly make sense
to me. That might be a more efficient way to get this done.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 22 02:44PM

On Thu, 2019-08-22, stdcerr wrote:
> On Tuesday, August 20, 2019 at 5:07:52 PM UTC-7, Sam wrote:
...
 
> I'm mostly using the Internet to find out things now, I've been
> writing C for many years and know a little about C++(obviously not
> much/enough) - any good book you would recommend?
 
I think you do need a book, for the bigger picture at least.
 
Stroustrup: The C++ Programming Language. The edition that covers
C++11.
 
Disclaimers:
- Don't know if there's a C++17 edition or whatever on the way.
I use the C++11 book and use online sources for the relatively
smaller changes after 2011. For the standard library details I
almost always go online.
- Other recent books may be good.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Tim Rentsch <tr.17687@z991.linuxsc.com>: Aug 22 04:47AM -0700

> g++ -c *.o
> ld -o prog *.o
 
> [...]
 
Forgive me if this is a dumb question. Is there some reason
you have to use gcc in the first step? How about doing this
instead:
 
g++ -x c -c *.c
g++ -x c++ -c *.cpp
g++ -o prog *.o
 
Substituting clang for g++ should also work here. Disclaimer: I
haven't verified anything beyond confirming that both g++ and
clang accept the -x c and -x c++ options.
gazelle@shell.xmission.com (Kenny McCormack): Aug 22 12:12PM

In article <864l29ifqm.fsf@mailhub.linuxsc.com>,
Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
...
 
>Substituting clang for g++ should also work here. Disclaimer: I
>haven't verified anything beyond confirming that both g++ and
>clang accept the -x c and -x c++ options.
 
I didn't even think you needed the -x option, as long as your files have
recognized extensions. For example, when compiling normal C code, your
files have extenion ".c" and you don't need any "-x c" option. You only
need "-x" if you need to override the default *or* you're in a situation
where gcc can't figure out what type of file it is (e.g., you are reading
the program text from stdin).
 
There is a list somewhere of the recognized extentions and which language
they are associated with.
 
--
When someone tells me he/she is a Christian I check to see if I'm
still in posession of my wallet.
David Brown <david.brown@hesbynett.no>: Aug 22 03:08PM +0200

On 22/08/2019 14:12, Kenny McCormack wrote:
> need "-x" if you need to override the default *or* you're in a situation
> where gcc can't figure out what type of file it is (e.g., you are reading
> the program text from stdin).
 
"gcc file" will compile "file.c" as C, and "file.cpp" as C++. But "g++
file.c" will compile the file as C++ rather than c. (I'm not asking
anyone to like this, I just saying the way it works.) The "-x" switch
lets you override the language choices of "gcc" or "g++".
 
However you choose to invoke gcc, I'd also recommend you explicitly
choose the standard you want - "-std=gnu++17", "-std=c++14", or whatever
suits your needs. The default here has changed before, and will change
again in the future.
 
 
> There is a list somewhere of the recognized extentions and which language
> they are associated with.
 
<https://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html>
<https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html>
Tim Rentsch <tr.17687@z991.linuxsc.com>: Aug 22 05:05AM -0700


> ... valid?
 
> I'd guess that it's not valid as C++11, but possibly valid as
> C++14 or later.
 
fwiw, g++ and clang accept it without complaint under -std=c++14
and -std=c++17, but give a diagnostic under -std=c++11. That
result holds both with and without a -pedantic option.
David Brown <david.brown@hesbynett.no>: Aug 22 01:30PM +0200

On 21/08/2019 21:39, Chris Vine wrote:
> generates randomly incorrect results and gives rise to a race condition
> in common parlance.
 
> It is important to be clear which case you are in fact referring to.
 
That's some good points.
 
It is /relatively/ easy tell if you have no data races in your code even
if you are not strict about using C++11/C11 atomics or
implementation-specific atomics. If your code does not access
potentially shared objects that are bigger than the hardware's write
size, and it only uses reads or writes to them (it doesn't assume that
"x += 1;" is atomic), then you are not going to get data races. When
two 32-bit cores both try to write to the same 32-bit memory address,
one core will hit first - you are not going to get a mixed write unless
you have a rather unusual and specialised system.
 
You might have noticed quite a few if's there - you have to be quite
restricted in your code to avoid the possibility of data races (as
defined by the C++ standard). And without additional guarantees from
your hardware, such as a total ordering on volatile accesses, it is not
going to be enough to be useful. If your system is relatively simple -
like a single core microcontroller - then you /do/ have such guarantees,
and "volatile" can be enough. For the OP, however, he doesn't have such
hardware - and "volatile" is not going to cut it.
 
Proving that you don't have any more general "race conditions" or
improper synchronisation is a lot harder.
 
> is atomic at the hardware level, such as an int, has identical effect
> to using the equivalent atomic variable with relaxed memory ordering.
> The code emitted by the compiler is identical.
 
Agreed.
 
I can imagine machines for which that is not the case - perhaps using
caches which do not snoop between other cpus' caches. This would make
some aspects of programming significantly harder, but could make
hardware a lot simpler (and therefore faster and/or cheaper). I'd
expect to see it only in quite specialised systems.
 
> code unnecessarily" seems to me to be a reasonable answer, provided the
> program is indeed adequately synchronized by some other means such as
> fences, so that it does not contain a race condition in common parlance.
 
Volatile accesses have certain advantages over atomics - even relaxed
atomics. Let us restrict ourselves to the world of single-core systems,
as is typical for microcontrollers - since when you have multi-core
systems you will be needing atomics and locks (correctness trumps
efficiency and convenience every time, and we know volatile is not
enough for most purposes in such systems). We'll assume a 32-bit system
for convenience.
 
Such systems are often asymmetric in their threading. You have a
hierarchy. If you have a RTOS, you have a layers of threads that have
strictly controlled priorities. A higher priority thread can pre-empt a
lower priority thread, but not vice versa - but complicated by priority
boosting at times. Above that, you have layers of interrupts at
different priorities, usually more strictly prioritised.
 
Imagine a timer interrupt function that tracks time as a 64-bit counter.
The "global_timer" variable is only ever written within that interrupt
function. It can be declared "int64_t global_timer;", and incremented
as "global_timer++;". This is safe - no need for atomics, volatile, or
anything else - these would be pessimisations. For code that reads this
value from another thread or context, you need to be smarter. Here you
/do/ need volatile accesses.
 
#define volatileAccess(v) *((volatile typeof((v)) *) &(v))
 
(Forgive the gcc'ism and C style - in C++, you'd make a template but it
doesn't affect the principle.)
 
You can read your global timer in various ways, such as:
 
disable_interrupts();
int64_t now = volatileAccess(global_timer);
enable_interrupts();
 
or
 
int64_t now = volatileAccess(global_timer);
int64_t now2 = volatileAccess(global_timer);
while (now != now2) {
now = now2;
now2 = volatileAccess(global_timer);
}
 
(You can also break this last one into separate high and low words to be
slightly more efficient.)
 
 
Both of these are much more efficient than using relaxed 64-bit atomic
access, as such accesses are often implemented. Even more importantly,
both of them /work/ - unlike some implementations I have seen of atomic
accesses (like
<https://gcc.gnu.org/wiki/Atomic/GCCMM?action=AttachFile&do=view&target=libatomic.c>)
which rely on spinlocks.
 
 
A key point here with volatiles is that you can have a normal object,
and use volatile accesses on it. You can't do that with atomic objects,
in the way you can with the macro above, limiting your flexibility to
use your knowledge of the program to use different access types for
different balances of efficiency and synchronisation control. It's true
that a relaxed atomic load or store is going to be efficient for small
enough sizes - and the cost is just the ugly and verbose syntax. For
larger sizes, it's a different matter. If your code is within a
critical section (due to a lock, or interrupt control) and you know it
cannot possibly clash with other access to the same object, there is a
huge efficiency difference between using a normal access to the object,
and using an atomic access (even a relaxed one).
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: