- We've won! - 13 Updates
- How to detect wrong Constructor usage... Object A(arguments) vs Object(arguments) - 3 Updates
- [Modération JNTP] Annulation de <pt3vrt$csi$5@dont-email.me> - 1 Update
- My Scalable Parallel C++ Conjugate Gradient Linear System Solver Library was updated - 1 Update
- Is this sorting predicate ok? - 2 Updates
- Longest word in a dictionary problem -- which container - 4 Updates
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 21 01:57AM +0100 On 20.11.2018 19:24, Mr Flibble wrote: > Except for reference parameters, arguments are /never/ mutated > I quite often mutate function parameters treating them as local function > variables. There's as yet no real distinction between "parameter" and "argument", but some people do make such distinctions. One woman's "argument" is another mans "parameter". And vice versa. The Holy Standard seems to have a preference for "parameter" for templates and "argument" for functions. Some people say "argument" and "parameter" instead of "actual argument" and "formal argument", or "actual parameter" and "formal parameter". And presumably some people do the opposite. Now that we have Wikipedia as a direction guide for the most conformist segment of the population, which I believe constitutes about 98%, it's likely that they will all soon fall into line and say the same. But still it's IMO prudent to be lenient in what to accept, and precise in one's own formulations. I like the "actual" and "formal" qualifications. Cheers!, - Alf |
James Kuyper <jameskuyper@alumni.caltech.edu>: Nov 20 09:09PM -0500 On 11/20/18 19:57, Alf P. Steinbach wrote: >> variables. > There's as yet no real distinction between "parameter" and "argument", > but some people do make such distinctions. Mpst importantly, the C++ standard makes such a distinction, and relies upon that distinction to clearly specify it's meaning. You can't properly understand what the standard says using those words unless you interpret them in the manner defined by that standard. One woman's "argument" is > another mans "parameter". And vice versa. > The Holy Standard seems to have a preference for "parameter" for > templates and "argument" for functions. No, the standard isn't Holy, It's authoritative, but because it's an ISO standard, not because of anything of a religious nature, nor because of any misguided belief that it's perfect or flawless. The standard very explicitly defines the meanings of both "parameter" and "argument", and it provides separate (and parallel) meanings for both words for functions, function-like macros, templates, throw/catch code: > argument > <template instantiation> constant-expression, type-id, or id-expression in the comma-separated list bounded > by the angle brackets (14.3) ... > And presumably some people do the opposite. > Now that we have Wikipedia as a direction guide for the most conformist > segment of the population, which I believe constitutes about 98%, it's It's not about being a conformist - it's about understanding the meaning of the standard, and about communicating clearly about that meaning. If you want to understand and be understood, your best bet is to stick to the definitions provided by the C++ standard in any context where the C++ standard is relevant. If you don't care about understanding or being understood, go ahead and use the terms any way you wish. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 21 06:18AM +0100 On 21.11.2018 03:09, James Kuyper wrote: >> segment of the population, which I believe constitutes about 98%, it's > It's not about being a conformist - it's about understanding the meaning > of the standard, and about communicating clearly about that meaning. This was not a discussion about the C++ standard. C++ standardese literal text has its place, of course. General programming discussion is usually not such a place. > you want to understand and be understood, your best bet is to stick to > the definitions provided by the C++ standard in any context where the > C++ standard is relevant. I don't agree that the context under discussion is one where the literal text of the C++ standard is important. But considering such contexts: that still /depends/. Consider C++17 §16.3.3.1.2/1 <quote> A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined conversion (15.3) followed by a second standard conversion sequence. If the user-defined conversion is specified by a constructor (15.3.1), the initial standard conversion sequence converts the source type to the type required by the argument of the constructor. </quote> Here the "source type" in the last sentence, is clearly the type of an actual argument. The last sentence can't therefore be talking about converting that type to the type of the actual argument: it's already that type. So "the argument of the constructor" must be referring to the constructor's formal argument. Hence, understanding ¹the general programming terminology, and how very far from clear-cut unambiguous it is, is key to understanding at least some parts of the C++ standard. Because that standard is not quite perfect. ;-) > If you don't care about understanding or being > understood, go ahead and use the terms any way you wish. I hope you see how irrelevant that advice is, now. Cheers!, - Alf Notes: ¹ https://en.wikipedia.org/wiki/Parameter_(computer_programming) |
David Brown <david.brown@hesbynett.no>: Nov 21 08:18AM +0100 On 20/11/2018 20:32, Christian Gollwitzer wrote: > Now I'm confused. It is OK to put const in the formal parameter to catch > bugs - I agree, and I did the same thing before. But it it is not OK to > put it in the declaration? How should this work? Don't they need to match? In the parameters of a function declaration that is not a definition, qualifiers ("const" and "volatile") are ignored. (This applies to the parameter itself, not any other parts of the type. A pointer-to-const-int is different from a pointer-to-int, but a "const int" is treated the same as an "int".) Still, you may prefer to keep the declaration and the definition exactly the same. I do - I use the same parameter names in declarations for a function as in the definition, and I use the same "const" (or rather, lack of it). |
Bonita Montero <Bonita.Montero@gmail.com>: Nov 21 09:12AM +0100 >> overhead for the performance-relevant case that no exception is thrown. > There are no runtime-based exception handling algorithms with zero > overhead, short of entirely static systems that are profiled. Correctly implemented, table-driven exception-handling has zero overhead for the performance-relevant case that no exception is thrown. |
Bonita Montero <Bonita.Montero@gmail.com>: Nov 21 09:13AM +0100 > There are no runtime-based exception handling algorithms with zero > overhead, short of entirely static systems that are profiled. Read this: http://www.ut.sco.com/developers/products/ehopt.pdf |
David Brown <david.brown@hesbynett.no>: Nov 21 10:16AM +0100 On 20/11/18 15:20, James Kuyper wrote: >> function. > I think you mean "arguments", not "parameters". See the definitions of > those terms in 1.3.2 and 1.3.15 of the standard. Yes, that is what I should have written. > function is allowed to lack qualifiers on parameters that have those > qualifiers in the function definition, and it's conventional to take > advantage of that fact. Agreed. |
David Brown <david.brown@hesbynett.no>: Nov 21 10:25AM +0100 On 21/11/18 01:57, Alf P. Steinbach wrote: > There's as yet no real distinction between "parameter" and "argument", > but some people do make such distinctions. One woman's "argument" is > another mans "parameter". And vice versa. There is a distinction in the C standards - "argument" is the things in the function call, while "parameter" is the things in the function declaration and definition. The distinction has not always been clear, different languages have different terms, and people (such as myself) are not always accurate about following the terminology of the language. As far as I understand it, C++ standards follow the same distinction as for C, but with more nuances. See section 1.3 of the standards- > likely that they will all soon fall into line and say the same. But > still it's IMO prudent to be lenient in what to accept, and precise in > one's own formulations. I like the "actual" and "formal" qualifications. "actual argument" and "formal parameter" would probably make things as clear as they could be. Other than that, a little explanation of the context always helps - if someone writes about the "arguments in the function declaration", you know they actually mean parameters. |
David Brown <david.brown@hesbynett.no>: Nov 21 10:57AM +0100 On 20/11/18 16:25, Rick C. Hodgin wrote: > I disagree with this design philosophy. I believe it's better to > declare everything in one place, and then assign it in a documented > init { } block. Fair enough. You are not alone in preferring to declare variables together at the start of a block (usually the start of a function), and assign to them later rather than initialising them. Just be aware that initialisation and assignment are different. They usually - especially in C, and with an optimising compiler - have the same effect in practice. But you can't assign to a "const" variable, you can only initialise it. And in C++, initialisation (construction) can be very different from assignment. In particular, initialisation of objects can be a good deal more efficient than default construction followed by assignment later on. In C, something like "T x;" does not usually correspond to any generated code, but in C++ it certainly can do. So you will find "declare all your variables at the top of the function" style in C90 code, and amongst some C99/C11 programmers - but you will rarely find it in C++ programming. (I am not trying to persuade you here, just pointing out some issues for your consideration.) > some other location that's more optimized for you. But in this way, > everything is grouped / encapsulated in its area, able to be docu- > mented and understood at first glance. I agree that the compiler can move things around for optimisation. As for how much this affects documentation or understanding, I think the diplomatic answer is "it's not that simple, and it will vary case by case". > not be set after this state is established. Depending on the > dynamics of the code at work using that variable, this is either > by known compiler state, or a hard internal flag. Well, for your language, you make the rules to suit yourself. Personally, I think: void my_function(void) { const int my_variable = populate_it(); // Other code here } is simpler, and clearer. It also makes it clear that "my_variable" is a really bad name, since it is immediately obvious that it cannot vary. Would it make a difference if there were lots of variables here, some of them constant (or read-only)? I don't think so, but you may have a different opinion. > { > [|readonly|] int my_variable; > ... I am lost here - I can't see the use-cases. If I want to say something can't be changed, I define it as "const". I don't want to be able to make it non-const later on. If I want a read-write version, I make a new variable initialised to the const's value. Conversely, if I want to say something can be changed, I define it without "const". If I want an unchanging copy of it, I define a new "const" variable initialised from the variable. (This may just be another case where you want to give programmers flexibility, and I like there to be more concrete rules.) > and if you need something else that can't be shifted through tra- > ditional pointer manipulation ... use a reference, or even pass > it by value if the source doesn't need to be altered. Sometimes you want to change where a pointer points, other times you don't. const pointers have their place. It is certainly the case that many, perhaps most, uses of const pointers in C can be replaced by references in C++, but they are still not entirely pointless. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 21 05:17AM -0800 On Wednesday, November 21, 2018 at 3:12:28 AM UTC-5, Bonita Montero wrote: > > overhead, short of entirely static systems that are profiled. > Correctly implemented, table-driven exception-handling has zero overhead > for the performance-relevant case that no exception is thrown. It's an interesting approach. I considered something similar, but equated it to being a little too dangerous and risky. It's better to have an observed runtime construction in my opinion. And in those places / cases where performance is truly an issue, don't use try..catch at every instance, but implement something else that's custom with a larger outer parent try..catch to min- imize the impact on oft-called functions. A set of enum constant values can be used to populate a single member variable indicating where the exception took place. Minimal overhead, and nothing fancy required. Note also: The author of the PDF you linked cited it does have some per- formance overhead. It has a large footprint in RAM at all times, removes some optimizations which may otherwise be em- ployed in normal code (in the code that does not generate exceptions), and has some additional slower performance in processing exceptions in unwinding and recovery. The author cites that some (rather extraordinary) effort can be applied to overcome many of the non-exception-case performance issues, but the memory footprint and slower exception handling cannot be overcome. IMO ... it's a questionable approach. But, I have no doubts it would work. I just wouldn't use its design. -- Rick C. Hodgin |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 21 05:27AM -0800 On Wednesday, November 21, 2018 at 4:57:53 AM UTC-5, David Brown wrote: > (I am not trying to persuade you here, just pointing out some issues for > your consideration.) I understand. I still stand behind the philosophy. > // Other code here > } > is simpler, and clearer... To me, the use of "const" can be confusing. Suppose it were const int* my_variable = populate_it(); ... it would be easy to become confused on if the value pointed to by the pointer is a constant, or if the pointer value itself is a constant. That confusion was in my mind a few days ago. It's still a little murky. :-) I believe a different approach is appropriate: Pointers should always be non-constant. And the values they point to only should ever be read-only or read-write, and I'm trying to convince myself to make a use case for write- only as well. > It also makes it clear that "my_variable" is a > really bad name, since it is immediately obvious that it cannot vary. It's still a variable. It's not a fixed quantity. It is populated externally, and used here as that value. > say something can be changed, I define it without "const". If I want an > unchanging copy of it, I define a new "const" variable initialised from > the variable. I believe the const/non-const state should be a policy when the input may be in read/write memory anyway. The only fixed cases are when it's in read-only memory. And in such a case, I don't think "const" is a good idea, but maybe [|locked|] or something, to indicate the value is locked and cannot be changed even with an override. There's probably a legal term for such a thing. I can re- member in the Bible there were laws issued or decreed which could not be revoked once issued. I don't remember if they had a special name though. I'm sure there's one somewhere that could replace "locked" with the proper term. > (This may just be another case where you want to give programmers > flexibility, and I like there to be more concrete rules.) The rules here would be concrete. You just have to follow policy / protocol. > don't. const pointers have their place. It is certainly the case that > many, perhaps most, uses of const pointers in C can be replaced by > references in C++, but they are still not entirely pointless. My approach is that pointers are just numbers, and if you have a value that you don't want to change, don't use a pointer, but use a commensurately sized unsigned integer, and then do the direct compare. Pointers are for pointing to data, and they should always be able to be manipulated. If you need something that should not be manipulated, don't use a pointer. Use some- thing else. -- Rick C. Hodgin |
James Kuyper <jameskuyper@alumni.caltech.edu>: Nov 21 09:15AM -0500 On 11/21/18 00:18, Alf P. Steinbach wrote: >>>>> Except for reference parameters, parameters are /never/ mutated >>>> I assume you meant to type: >>>> Except for reference parameters, arguments are /never/ mutated ... >> It's not about being a conformist - it's about understanding the meaning >> of the standard, and about communicating clearly about that meaning. > This was not a discussion about the C++ standard. This group is for discussing C++, the rules of which are set by that standard. The context of your comment was an incorrect statement of one of those rules. It was claimed, incorrectly, that function parameters are never mutated. The correct statement is that function parameters may freely be mutated unless declared "const"; it's function arguments that a function cannot mutate directly. I can't imagine a clearer example of the necessity of clearly distinguishing between parameters and arguments, and of doing so in a manner consistent with the standard's definitions of those terms. ... > far from clear-cut unambiguous it is, is key to understanding at least > some parts of the C++ standard. > Because that standard is not quite perfect. ;-) No, as you say, the standard is not perfect. Correcting that section to refer to the parameter rather than the argument is the key to making it more clearly understandable. Taking liberties in interpreting those words can lead only to more misunderstandings down the road, even if those liberties happen to give you a correct understanding in this case. >> If you don't care about understanding or being >> understood, go ahead and use the terms any way you wish. > I hope you see how irrelevant that advice is, now. No, I see how relevant it is to precisely the cases you presented as counter-examples. |
David Brown <david.brown@hesbynett.no>: Nov 21 09:57PM +0100 On 21/11/2018 14:17, Rick C. Hodgin wrote: > cannot be overcome. > IMO ... it's a questionable approach. But, I have no doubts > it would work. I just wouldn't use its design. Table-driven exception handling is by far the most common system used in modern C++ compilers. It takes extra code space for the unwind tables - these are rarely an issue (except for constraint-limited embedded systems). Yes, you get some optimisation limitations, such as limitations on the amount of re-ordering and moving the compiler can do, especially on object construction and destruction. But you get that kind of limitation with any C++ exception implementation - when compiling code which has an external call, the compiler does not know if the function can throw an exception, and must order code on the assumption that it might. The common alternative strategy for C++ exceptions is to store lists of destructors on the stack. This avoids the need to generate long tables in code, but uses more run-time memory and stack space, and means fewer functions can skip having a stack frame. It has higher run-time speed costs for code that does not throw an exception, but works faster when an exception is thrown. |
Jan Riewenherm <vollasso@googlemail.com>: Nov 21 06:05AM -0800 Hi, i´ve got an issue where i do not really find a proper solution. We have locking objects that take a pointer as argument and protect simultaneous access to the same object from different threads. These locking objects have a singleton in the backed but thats not the point of interest here. What i would like to prevent is that the locking object is used in the wrong way. Code Snippped of the locking helper object. class LockingObject { LockingObject(void* pObjectToLock) { Singleton_Lock(pObjectToLock); } ~LockingObject() { Singleton_Unlock(m_pObjectToLock); } private: void* m_pObjectToLock } How to use the locking object: function test() { LockingObject object(this); do_something_on_this(); } As soon as the locking object is created the simultaneous access is protected. As soon as i run out of the scope of my function the locking objects is freeed. The problem i have: function test() { LockingObject(this); do_something_on_this(); } How to prevent calling the constructor where the created object is not used at all? c++17 [[nodiscard]] does not work for Constructors. The locking object is a very generic approach to lock access from different threads and leads to a very low ressource consumption as i do not need to have dedicated locking objects for members or functions i want to protect. So please do not take a closer look at how other locking mechanisms might work. I would like to focus on the problem of having constructors which do not actually create an object. Any advice appreciated. Jan |
"Öö Tiib" <ootiib@hot.ee>: Nov 21 07:56AM -0800 On Wednesday, 21 November 2018 16:06:08 UTC+2, Jan Riewenherm wrote: > { > Singleton_Lock(pObjectToLock); > } That constructor leaves private member m_pObjectToLock uninitialized. > { > Singleton_Unlock(m_pObjectToLock); > } That destructor passes uninitialized member. > function test() > { > LockingObject(this); Note that the temporary constructed above must be destroyed by now. > do_something_on_this(); > } > How to prevent calling the constructor where the created object is not used at all? c++17 [[nodiscard]] does not work for Constructors. Technically it is possible to replace that particular public constructor with a public factory method and private constructor. Inlining and RVO might achieve that there are no performance differences. The compilers do not warn there because it might be code as its designer desired: std::ofstream("filename"); // creates ./filename if it doesn't exist Philosophically all useful languages have to allow endless ways to express lies and nonsenses for to achieve that at least some truths can be expressed in those as well. Blocking all lies and nonsense will be achieved only when nothing useful can be expressed anymore. > The locking object is a very generic approach to lock access from different threads and leads to a very low ressource consumption as i do not need to have dedicated locking objects for members or functions i want to protect. So please do not take a closer look at how other locking mechanisms might work. I would like to focus on the problem of having constructors which do not actually create an object. > Any advice appreciated. Always try to post code that compiles, runs and demonstrates the issue that you have. Otherwise it is hard to realize what sort of defect or lack of expertise is its cause. |
Paavo Helde <myfirstname@osa.pri.ee>: Nov 21 07:54PM +0200 On 21.11.2018 16:05, Jan Riewenherm wrote: > do_something_on_this(); > } > How to prevent calling the constructor where the created object is not used at all? c++17 [[nodiscard]] does not work for Constructors. Define a macro #define SCOPED_LOCK(x) LockingObject object(x); and make a rule to use only this macro throughout the code base: void test() { SCOPED_LOCK(this); // ... } I use this all the time, works fine for avoiding temporary objects (although TBH the initial motivation for using a macro was to have correct __FILE__ and __LINE__ for debugging purposes). |
Elephant Man <conanospamic@gmail.com>: Nov 21 04:09PM Article d'annulation émis par un modérateur JNTP via Nemo. |
Horizon68 <horizon@horizon.com>: Nov 21 08:07AM -0800 Hello... My Scalable Parallel C++ Conjugate Gradient Linear System Solver Library was updated The Dense Linear System Solver library was updated to version 1.72 You can download it from: https://sites.google.com/site/scalable68/scalable-parallel-c-conjugate-gradient-linear-system-solver-library Thank you, Amine Moulay Ramdane. |
"Öö Tiib" <ootiib@hot.ee>: Nov 21 01:12AM -0800 On Tuesday, 20 November 2018 23:38:31 UTC+2, Jorgen Grahn wrote: > 0 + x == x 0 | x == x > 0 * x == 0 0 & x == 0 > (But again, I have no use of this knowledge.) I have memorized the precedence for ages but still find that some "redundant" parentheses often help me to read complex expressions. On current case the OP predicate is not ordering its arguments but lack of parentheses feels to make that harder to realize. |
"Öö Tiib" <ootiib@hot.ee>: Nov 21 05:46AM -0800 On Tuesday, 20 November 2018 02:13:33 UTC+2, Paul wrote: > But it doesn't need memorization or looking it up. The precedence between > || and && can't be different from the precedence between + and *. > Surely everyone knows that true || false && false means true || (false && false) which == true. Still there seems to be confusion exactly there because logic of your predicate does not follow logic that your describe in prose. Also there seem to be difference *exactly* in parentheses misplaced. That is what your code does: return word1.size() <= length && word2.size() > length || word1.size() > word2.size(); That seems to be what you describe in prose: return word1.size() <= length && (word2.size() > length || word1.size() > word2.size()); Notice the parentheses. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 21 01:50AM +0100 On 19.11.2018 11:19, Paul wrote: > std::unordered_set<std::string> words = {"acceca", "ace", "acce", "accce" }; > std::cout << LongestWord("acecad", words); > } "acce", said to be a correct answer, doesn't contain all the characters in "acecad". As an example of another word that contains /some/ of the characters, "ace" does. None of words contain /all/ of the characters. And none of the words are /permutations/ of the characters. What's the rule here? Cheers!, - Alf |
Louis Krupp <lkrupp@nospam.pssw.com.invalid>: Nov 20 11:49PM -0700 On Tue, 20 Nov 2018 14:55:35 -0000 (UTC), Juha Nieminen >until you have gone through the entire word. >The above is a bit lacking as a full algorithm explanation, but I'm sure >it ought to be enough to give an idea. True, the implementation isn't complicated, but in my opinion describing what it does takes longer than laying out these steps: 1. Sort the letters in the pattern. 2. Generate a regular expression. 3. Sort the letters in each input string. 4. Call routines in <regex> to do the matching. 5. Keep track of the longest matching input string. The regular expression library has been tested, so there's (hopefully) no need to worry about that. If you'd rather do everything in, say, Python, the steps are simple. If you want it to happen faster, use C++ and <regex>. If it's still not fast enough, the implementation you laid out is probably the way to go. Doing it first with regular expressions -- whether it's in Python or in C++ -- would give you a baseline you could use for testing. ( I almost said "do it in Python or a shell script" but then I thought about what a nightmare it would be to do it in a shell script. There was a time when I would have said "Perl," meaning Perl 5, but that's out of fashion now, so ... Perl 6. Yes, that's it. Perl 6. :)) Louis |
Juha Nieminen <nospam@thanks.invalid>: Nov 21 07:40AM > to go. Doing it first with regular expressions -- whether it's in > Python or in C++ -- would give you a baseline you could use for > testing. Firstly, I have my doubts that building an ascii string that's a regexp that does what you want is any simpler than doing the comparison yourself. Secondly, the original task is, essentially and pretty much, comparing binary bytes to each other. Going the route of creating a dynamic string from the binary data, have a library parse that string, allocate more data containers within itself (probably some kind of tree or such), and then run a complicated regexp matching algorithm not only sounds like it's needlessly inefficient, but also needlessly complicated for such a relatively simple task. It's like shooting flies with a cannon. Thirdly, depending on what kind of thing it is that the task is trying to teach, it may actually be more didactic and beneficial to do the comparison yourself, as a programming exercise. |
Louis Krupp <lkrupp@nospam.pssw.com.invalid>: Nov 21 03:47AM -0700 On Wed, 21 Nov 2018 07:40:05 -0000 (UTC), Juha Nieminen >Thirdly, depending on what kind of thing it is that the task is trying >to teach, it may actually be more didactic and beneficial to do the >comparison yourself, as a programming exercise. The world would be a scary place if everyone agreed with me. Louis |
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