- Why does this work on Xcode ??? - 7 Updates
- "C++: Size Matters in Platform Compatibility" - 3 Updates
- About getters/setters - 10 Updates
- [Jesus Loves You] [announcement] Fast C++ JSON/RJSON parser - 2 Updates
- About getters/setters - 1 Update
- What is easiest to use static C++ code analyser? - 2 Updates
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 23 07:22AM +0200 On 23.08.2019 00:45, Ben Bacarisse wrote: >> 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. > Why do you think no one else shares Tim's opinion? Because he's been arguing his view for a very long time and nobody's supported him. Also because it's a totally impractical view so I'd not expect any practitioner to support it. > Tim has not said anything here about UB that I disagree with. Well then, speak up in defense of his view. > You have, but I've found > my life to be more pleasant if I don't reply to your posts, and anyway, > Tim has it covered. If I have said things that you disagree with about UB, then most likely so have everybody else who's responded to Tim on this subject. As far as I recall you didn't speak up at any point, so your explanation, that you're afraid of replying to /me/, just doesn't hold water. So, your explanation for keeping silent appears to be an untruth that you know is an untruth, anyway embedded in an ad hominem attack. The thread has been civilized so far, but now (1) Tim has added a social silly-argument (that to disagree with him one must think of oneself as smarter than all people on the committee), and (2) you add an untruth and an ad hominem attack. That development of dishonest more social argumentation is probably about something else than that you now suddenly feel you're losing a technical debate. Because you lost this debate very long ago: roughly nobody agree with you that exceeding resource limits isn't UB. The standard says it is. And that was noted early on, and repeated a gazillion times. Cheers!, - Alf |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Aug 23 01:12PM +0100 >> Why do you think no one else shares Tim's opinion? > Because he's been arguing his view for a very long time and nobody's > supported him. That's not a sound basis for making that assumption. > Also because it's a totally impractical view so I'd not expect any > practitioner to support it. Impractical views can be correct. As it happens, I don't see this view as an impractical one, but either way it can still be correct. >> Tim has not said anything here about UB that I disagree with. > Well then, speak up in defense of his view. I don't see what I can add. Tim is a far better writer than I am and has (I my opinion) put the case accurately and clearly. I don't hold with the modern idea that my opinion matters, just because I have it. I try to offer my opinion only when I can see some point in doing so. I chipped in here only because I thought it would be useful to know that silence can't be read as support for either one view or another. > subject. As far as I recall you didn't speak up at any point, so your > explanation, that you're afraid of replying to /me/, just doesn't hold > water. Sorry, it was not intended as an explanation for why I did not reply to other people (and I did not say I was afraid to reply). There is no one reason that will explain every time I choose more to post. > So, your explanation for keeping silent appears to be an untruth that > you know is an untruth, anyway embedded in an ad hominem attack. Why the Latin? "ad hominem" brings to mind a logical fallacy, but I am not making any logical argument at all. My remark was entirely emotional. Whilst I enjoy reading your posts, I have not enjoyed my reaction to our direct exchanges. That says as much about me as it does your posts. > social silly-argument (that to disagree with him one must think of > oneself as smarter than all people on the committee), and (2) you add > an untruth and an ad hominem attack. I don't think it's uncivilised to say what I said, and I think it's an extreme exaggeration to call what I wrote an attack. As I said, it's as much about my reaction as it about your posting style. > That development of dishonest more social argumentation is probably > about something else than that you now suddenly feel you're losing a > technical debate. I am not engaged in a technical debate. I don't recall making any technical contribution at all. > Because you lost this debate very long ago: roughly nobody agree with > you that exceeding resource limits isn't UB. The standard says it > is. And that was noted early on, and repeated a gazillion times. Then your replies make no sense to me. If it is so clearly settled (in C++, I presume -- maybe C is different here), just cite the unequivocal text that settles the matter. If anyone disagrees, cite the text again. -- Ben. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 23 09:28AM -0400 On 8/23/19 1:22 AM, Alf P. Steinbach wrote: >> Why do you think no one else shares Tim's opinion? > Because he's been arguing his view for a very long time and nobody's > supported him. I normally try (and often fail) to avoid paying attention to his posts, because I've found discussions with him to be unproductive - when I discuss my disagreements with him, we usually both end up wasting a lot of time failing to convince each other. He's a lot like you in that regard. He has a strong tendency to elevate what he believes to be the committee's intent to play a larger role in the interpretation of the standard than I think appropriate. This can be particularly annoying if I disagree with him about what that intent was. If the standard's wording is in conflict with (or even simply fails to clearly express) the committee's intent, then that wording should be corrected to clearly express that intent - but that discrepancy doesn't change the meaning of the words that they actually wrote. However, he is very knowledgeable about the standard, and he is correct about the pre-eminence of a program's observable behavior. The standard's definition of "observable behavior" is not "behavior which can be observed" - it's far more specific than that: "The least requirements on a conforming implementation are: — Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine. — At program termination, all data written into files shall be identical to one of the possible results that execution of the program according to the abstract semantics would have produced. — The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input. What constitutes an interactive device is implementation-defined. These collectively are referred to as the observable behavior of the program. ..." (4.6p7). The term "observable behavior" is in italics, an ISO convention indicating that this sentence is the official definition of that term. In the context of the C++ standard, that definition overrides any alternative interpretation that might otherwise seem appropriate. Note that the amount of stack space taken up by a program does not qualify as "observable behavior". The standard very explicitly says "The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below." (4.6p1). So if the same observable behavior can be achieved by using either an iterative or a recursive algorithm, an implementation is free to use either of those algorithms to achieve it, regardless of which algorithm you actually expressed in your code. The fact that one algorithm runs a higher risk of running out of stack space than the other imposes no requirement on the implementation to avoid that risk (or to embrace it, for that matter). |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 23 04:02PM +0200 On 23.08.2019 14:12, Ben Bacarisse wrote: > C++, I presume -- maybe C is different here), just cite the unequivocal > text that settles the matter. If anyone disagrees, cite the text > again. That's what's been done, by others and by me. And evidently that's not enough, but I've run out of ideas about what would help. Anyway, yet again, but for your convenience, first consider C++17 §1.4/2.1: [quote] If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute that program. [/quote] There are no requirements, here or anywhere else in the standard, about what should happen or not if the program is not executable within the implementation's resource limits. There is a requirement, the quoted text, if the the execution is within the resource limits. There are no requirements otherwise. And "no requirements" is the definition of Undefined Behavior. C++17 §1.3.27 [quote] 1.3.27 [defns.undefined] undefined behavior behavior for which this International Standard imposes no requirements [/quote] One argument that has been made against this very clear and indisputable (really) wording, is that it doesn't mean that the defined term is equivalent to the stated definition, but rather that it just implies the apparent definition. Thus, in that distorted view, UB would imply no requirements, but no requirements would not necessarily imply UB. A common example of the conventional view, the equivalence of "UB" and "no requirements", is a `*p` dereferencing of a nullpointer outside of a `typeid` expression. Everybody (well, almost everybody!) agree that `*p` is Undefined Behavior because the standard imposes no requirements about it. If the one-way implication view was adopted, dereferencing that nullpointer would no longer be UB. The same goes for use of the referenced non-object, if any: in the conventional view it's UB because there are no requirements. With the one way implication view it's... what? I don't know, it just doesn't make sense to me. So, that view appears to be entirely silly, impractical, but the discussion continues, at least for me, i.e. this is my personal reason, because it's generally a good idea to flesh out what a so long standing disagreement is about. One can learn things from that. Still I'm as far as ever from understanding what it's really about. Cheers, - Alf |
David Brown <david.brown@hesbynett.no>: Aug 23 04:37PM +0200 On 23/08/2019 15:28, James Kuyper wrote: > higher risk of running out of stack space than the other imposes no > requirement on the implementation to avoid that risk (or to embrace it, > for that matter). Since we are expressing opinions - regardless of how much or little they may be worth - I agree with James here. And as far as I can see, it is the same as Tim has been saying in this regard. Usually, changing an iterative algorithm into a recursive one will be a pessimisation, taking more space and run-time. So it is highly unlikely for a compiler to do this sort of thing - it would quickly become an unpopular tool. But it is allowed to do so. In the same way, between "int a = b + c;" and "int d = a * 2;", the compiler is allowed to insert code calculating the first hundred digits of pi - including the stack space needed for the job. It would be an unpopular tool, but this would not affect the observable behaviour and thus it would not affect the conformance of the compiler. The standards do not impose any requirements on quality of implementation (though they have a few hints here and there) - that is up to the user. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 23 11:07PM +0200 On 23.08.2019 16:37, David Brown wrote: > pessimisation, taking more space and run-time. So it is highly unlikely > for a compiler to do this sort of thing - it would quickly become an > unpopular tool. But it is allowed to do so. As an example, rewriting a function with loop that uses a fixed size storage known at compile time, to a recursive function that uses storage proportional to the function argument, changes the behavior. With the original code one is guaranteed that it will complete. With the recursive one one is not guaranteed completion, because for large enough values of the parameter it will run out of stack space, an implementation limit. * * * Essentially the argument about observable behavior is therefore that a compiler is formally permitted to change a program that guarantees a result if it compiles and loads, into a program that almost guaranteed does not produce a correct result. That's a perpetuum mobile construction argument. One doesn't necessarily know where someone's logic went astray so that they ended up with a perpetuum mobile design, but the end result is just not reality: it's absurd. Somewhere in that argument there's necessarily something wrong, and that's not a QoI issue. > In the same way, between "int a = b + c;" and "int d = a * 2;", the > compiler is allowed to insert code calculating the first hundred digits > of pi - including the stack space needed for the job. No, that's not the same way. In this example a fixed storage requirement is not changed to a requirement of storage depending on a parameter. > It would be an > unpopular tool, but this would not affect the observable behaviour and > thus it would not affect the conformance of the compiler. It would affect observable behavior. One would get wrong results or crashes. Instead of with a conforming compiler, correct results. > The standards do not impose any requirements on quality of > implementation (though they have a few hints here and there) - that is > up to the user. That's right, but this isn't QoI, it's about correctness. Cheers!, - Alf |
Richard Damon <Richard@Damon-Family.org>: Aug 23 07:10PM -0400 On 8/23/19 5:07 PM, Alf P. Steinbach wrote: > That's right, but this isn't QoI, it's about correctness. > Cheers!, > - Alf The Standards unfortunately leave a LOT to QoI. For instance, as far as I know, the compiler would be free to implement unsigned i = 1; unsigned j = 5; unsigned k = i + j; as k = __add_uint(i, j); where __add_uint() was defined as: unsigned __add_uint(unsigned i, unsigned j) { if(j) return __add_uint(++i, --j); else return i; } You might even need something like this (but maybe iterative instead of recursive) for a processor with very limited arithmetic operations (just increment/decrement). One such an implementation, the program int main() { unsigned i = 1U + 65000U; } might fail due to exhaustion of resources, and that is ok by the standard. The Standard just requires that there be ONE program that reaches all of the specified resource limits that the implementation can process, any other program is allowed to fail for resource limits. This 'one program' rule is one of the big holes in the Standard (at least in my opinion). |
Richard Damon <Richard@Damon-Family.org>: Aug 22 10:58PM -0400 On 8/21/19 2:30 PM, Eli the Bearded wrote: > Elijah > ------ > given MS, probably whatever calender Redmond was on in 1995 I thought it was 3 days per 400 years, the multiples of 100 which aren't multiples of 400 which are the ones the Gregorian Calendar omitted. |
Richard Damon <Richard@Damon-Family.org>: Aug 23 02:14PM -0400 UTF-16 takes 2 bytes for values 0-0xFFFF (Unicode Base Plane) 4 bytes for values 0x10000 - 0x10FFFF (All of current Unicode) it CAN'T handle higher code points without some other extension which would get ugly. That is why Unicode has currently defined that 0x10FFFF will be the highest code point. I suspect at some point there will be pressure to change that. UTF-8 takes 1 byte for values 0 - 0x7F (basically ASCII) 2 bytes for values 0x80 - 0xFFF (most western languages) 3 bytes for values 0x1000 - 0xFFFF (Unicode base plane, much of this is the CJK group) 4 bytes for values 0x10000 - 0x10FFFF, but can actually get to 0x1FFFF if they extend unicode to higher code points) in the extension (and earlier definition) 5 bytes for values 0x200000 - 0x3FFFFFF 6 bytes for values 0x400000 - 0x7FFFFFFF UTF-16 is more compact only for code that has more characters in the range 0x1000 - 0xFFFF than in the range 0-0x7F. This MIGHT hold for Chinese/Japanese/Korean documents that have minimal markup in them. It largely also requires that CJK document has a lot of 'basic' CJK characters, as one big reason for extending the Unicode standard past 16 bits was that there were a LOT more characters needed then expected to handle them. It turns out that UTF-16 was a mistake. It came about because the first attempts at Unicode thought it could be a 16 bit characters set, and thus would be UCS-2. It only lives on really because Microsoft decided to use UCS-2 in windows instead of UTF-8, which admittedly might not have been a bad decision at the time. When UCS-2 had to become UTF-16 to handle the full character set, it gets the worse of both sides, it still is a multi-code character set (but maybe a lot of code can get away with ignoring it and just not work right with 'esoteric' characters), is less compact in the most common cases, and has a byte order issue for byte streams (which most data streams are). |
Eli the Bearded <*@eli.users.panix.com>: Aug 23 07:15PM >> which is around 0.0016 seconds day. That's a big jump in nanoseconds. > I thought it was 3 days per 400 years, the multiples of 100 which aren't > multiples of 400 which are the ones the Gregorian Calendar omitted. Hmmm. Yes. This is why I'm happy to use date libraries instead of writing my own. Elijah ------ there's too much to remember |
Ian Collins <ian-news@hotmail.com>: Aug 23 04:17PM +1200 On 23/08/2019 10:09, Tim Rentsch wrote: > never be public. There are cases where for data members might > plausibly be made protected rather than private, but never > public. There is a case where a data member is safe to be public: a const data member. Access to such a member cannot change a class's invariants. -- Ian. |
JiiPee <no@notvalid.com>: Aug 23 07:09AM +0100 On 22/08/2019 23:09, Tim Rentsch wrote: > that some other people have commented on, and assuming your > question is meant as generic, with 'age' being merely an > unfortunate choice of example.) correct. the example given might not have been the best. general question about all situations. > fred.siblings() += 1; // a new birth in fred's family > To me this pattern reads nicer on the client side than set/get > functions. yes many seems to suggest this online |
JiiPee <no@notvalid.com>: Aug 23 07:13AM +0100 On 22/08/2019 23:22, Stefan Ram wrote: > Instead of asking the object for data and the processing > to data outside of the object (as when using accessors), > you should tell the object to do the processing itself. sometimes its about storing global settings like: struct Settings { Color backgroundColor; int fontSize; .... }; So I guess this class is not really meant to operate with the values only return them? it just bundless a group of data. |
David Brown <david.brown@hesbynett.no>: Aug 23 09:30AM +0200 On 23/08/2019 08:13, JiiPee wrote: > }; > So I guess this class is not really meant to operate with the values > only return them? it just bundless a group of data. Classes like that still need to have protection. There may not be need for synchronisation between members for keeping invariants, but usually you don't want to allow any possibility of other parts of the code making uncoordinated changes to the values. |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 23 11:24AM On Thu, 2019-08-22, Stefan Ram wrote: > A class needs to protect its invariants. > Therefore, a member can be public only if it is not > mentioned in an invariant of the class. I think invariants (explicit or implicit) is why setters and getters bother me. Either you have a C struct with no invariants, and setters/getters are just unnecessary OO noise on top of non-OO code. Or you /do/ have invariants, and setting an individual member, at any time, threatens to break the invariant. Which doesn't mean there can be /no/ set/get methods, they won't map 1:1 to the members. > Instead of asking the object for data and then processing > the data outside of the object (as when using accessors), > you should just /tell the object/ to do the processing. Moving logic into the class instead of treating it like a dumb container. Also good advice (except of course when you /want/ a dumb container). /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Tim Rentsch <tr.17687@z991.linuxsc.com>: Aug 23 05:26AM -0700 > There is a case where a data member is safe to be public: a const > data member. Access to such a member cannot change a class's > invariants. My experience with const data members is that they are almost always more trouble than they're worth. Even in those cases where a data member is made const, it's better to stick to the simple rule that data members (other than pure structs) never be public, on general principles of information hiding: client code shouldn't know or care what particular data members a class has, let alone whether they are const or not. Any property an object wants to supply to its clients should be made available through a (usually const) member function, and only that, regardless of whether the property needs an elaborate computation or is simply returning the value of a data member -- even a const one. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 23 08:34AM -0400 On 8/23/19 7:24 AM, Jorgen Grahn wrote: ... > Or you /do/ have invariants, and setting an individual member, at any > time, threatens to break the invariant. Which doesn't mean there can > be /no/ set/get methods, they won't map 1:1 to the members. In general, I agree. However, a setter for a single member could make sense, if the applicable constraints allow two or more different values for that member, even if all other members are unchanged. For instance, the invariant might be current_value <= maximum_achieved_value. The setter for current_value would deal with changes that would violate that invariant, either by rejecting them or by increasing maximum_achieved_value (which corresponds to the last case you mention: a setter that changes two or more members in synchrony). |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 23 02:48PM On Fri, 2019-08-23, Stefan Ram wrote: >>invariant, either by rejecting them or by increasing >>maximum_achieved_value (which corresponds to the last case you mention: >>a setter that changes two or more members in synchrony). When I wrote "map 1:1 to the members" I was more thinking of someone going through all the members and adding a setter for each of them. > Behind all of this lurks the question: How does one define "setter"? How about "a method that's defined in terms of changing a certain part of the object, without considering the object as one single entity"? But I suppose that's my definition of a setter I dislike, rather than of all setters. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 23 03:49PM On Fri, 2019-08-23, James Kuyper wrote: > invariant, either by rejecting them or by increasing > maximum_achieved_value (which corresponds to the last case you mention: > a setter that changes two or more members in synchrony). I can imagine how that could end up with me breaking out: ValueWithHighwatermark<int> foo = 2; // 2, 2 foo = 3; // 3, 3 foo = 0; // 0, 3 I know it was just an example, but my gut feeling is that there are often solutions like that: to raise the abstraction level of the members. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Melzzzzz <Melzzzzz@zzzzz.com>: Aug 23 06:07PM >> public. > There is a case where a data member is safe to be public: a const data > member. Access to such a member cannot change a class's invariants. Also there is case when member is class with own interface. -- press any key to continue or any other to quit... U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi bili naoruzani. -- Mladen Gogala |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Aug 23 05:12PM +0100 > Lose this signature line and you'll remember me by its absence. > You've arrange your life just so, even in your rebellion. > But it's not me you're remembering, Leigh. It's Jesus. Far from it as like most sane people I don't read my own .sig when I post Usenet messages; I had completely forgotten about you until you posted the fucktarded message I am currently replying to. [spam nonsense snipped] /Flibble -- "Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin "You won't burn in hell. But be nice anyway." – Ricky Gervais "I see Atheists are fighting and killing each other again, over who doesn't believe in any God the most. Oh, no..wait.. that never happens." – Ricky Gervais "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." |
rick.c.hodgin@gmail.com: Aug 23 10:55AM -0700 https://www.youtube.com/watch?v=k5wknazzz9w -- Rick C. Hodgin |
ram@zedat.fu-berlin.de (Stefan Ram): Aug 23 01:23PM >>Or you /do/ have invariants, and setting an individual member, at any >>time, threatens to break the invariant. Which doesn't mean there can >>be /no/ set/get methods, they won't map 1:1 to the members. .. >invariant, either by rejecting them or by increasing >maximum_achieved_value (which corresponds to the last case you mention: >a setter that changes two or more members in synchrony). Behind all of this lurks the question: How does one define "setter"? |
legalize+jeeves@mail.xmission.com (Richard): Aug 22 11:38PM [Please do not mail me a copy of your followup] Szyk Cech <szykcech@spoko.pl> spake the secret code >What is easiest to use static C++ code analyser? Probably the easiest one to use is the one built into your C++ compiler. Clang: <https://clang-analyzer.llvm.org/> MSVC: /analyze <https://docs.microsoft.com/en-us/cpp/build/reference/analyze-code-analysis?view=vs-2019> gcc probably has something but nothing is turning up at the moment. Outside of the compiler, I have used cppcheck and it's easy to run outside of a build. <http://cppcheck.sourceforge.net/> The general advice is to run as many static analyzer tools as you can because they all have strengths and weaknesses and they haven't yet converged to have huge overlap, although there is some overlap. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Terminals Wiki <http://terminals-wiki.org> The Computer Graphics Museum <http://computergraphicsmuseum.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
legalize+jeeves@mail.xmission.com (Richard): Aug 22 11:38PM [Please do not mail me a copy of your followup] ram@zedat.fu-berlin.de (Stefan Ram) spake the secret code >>What is easiest to use static C++ code analyser? > Every static code analyzer is easy to use > (unless you want to use it under Windows). Lies. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Terminals Wiki <http://terminals-wiki.org> The Computer Graphics Museum <http://computergraphicsmuseum.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
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:
Post a Comment