- auto return type - 3 Updates
- Just some code - 18 Updates
- auto return type - 2 Updates
- Christianity is a religion - 1 Update
- "Modern C++ for C Programmers: part 1" - 1 Update
Sam <sam@email-scan.com>: Jun 27 05:14PM -0400 Stefan Ram writes: > auto f(); > is hardly helpful. So should we avoid the auto return type > for functions which are part of an API for this reason? Avoiding a very useful, new language feature only because a documentation tool can't deal with it doesn't seem like a good reason to me. With the increased complexity of C++, only an actual C++ compiler can fully understand C++ code. This is not the only part of modern C++ that doxygen doesn't quite pick up. I find doxygen very useful, and I use it a lot. I do not take into consideration doxygen's limitations when writing code. I only review doxygen's output after the fact; and make whatever manual fixes and tweaks to doxygen's output that can be reasonably done. |
Paavo Helde <myfirstname@osa.pri.ee>: Jun 28 12:34AM +0300 On 27.06.2018 23:29, Stefan Ram wrote: > auto f(); > is hardly helpful. So should we avoid the auto return type > for functions which are part of an API for this reason? Nope, the tools should be updated to cope with the new language rules. However, auto return type should be avoided in API-s because an API ought to define an interface (that's the I) but auto depends on the implementation details. With something having an official API it should be vice versa, implementation should depend on the interface. |
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jun 27 02:37PM -0700 On 6/27/2018 2:34 PM, Paavo Helde wrote: >> for functions which are part of an API for this reason? > Nope, the tools should be updated to cope with the new language rules. > However, auto return type should be avoided in API-s Agreed. |
guinness.tony@gmail.com: Jun 26 04:30PM -0700 On Sunday, 24 June 2018 06:39:37 UTC+1, Alf P. Steinbach wrote: > (args[1] == "--faux-text"? With_faux_text{}._ : > With_stream_detection{}._), app::run(); > } There are so many undeclared identifiers in that code soup that I cannot understand whatever "approach" it is that you are trying to convey. |
Juha Nieminen <nospam@thanks.invalid>: Jun 27 05:40AM > public: > const char _{ '-' }; Is this intentional obfuscation? |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 08:24AM +0200 On 27.06.2018 07:40, Juha Nieminen wrote: >> public: >> const char _{ '-' }; > Is this intentional obfuscation? It's a to me simplest possible and non-verbose conversion to a common type for the two type-wise unrelated struct types, so that they can be used in the same :?-expression: (args[1] == "--faux-text"? With_faux_text{}._ : With_stream_detection{}._), app::run(); I guess an alternative could be to derive them from a common base class, but I didn't try that. The details of the rules for :? elude me. I have to look them up every few years when I stubbornly write or by necessity delve into some tricky :? code. So in my humble opinion, better avoid those grayshade corners of the language, and Keep It Super Simple™ and obviously valid. :) Cheers!, - Alf |
David Brown <david.brown@hesbynett.no>: Jun 27 09:36AM +0200 On 27/06/18 08:24, Alf P. Steinbach wrote: > delve into some tricky :? code. > So in my humble opinion, better avoid those grayshade corners of the > language, and Keep It Super Simple™ and obviously valid. :) It is far, far better to Keep It Simple, Stupid - and use an "if". That rule trumps pointless DRY complaints every time: if (args[1] == "--faux-text") { With_faux_text w; app::run(); } else { With_stream_detection w; app::run(); } If you are really desperate to avoid duplicating app::run() here, make a template: template<typename T> void run_with(T with) { app::run(); } if (args[1] == "--faux-text") { run_with(With_faux_text()); } else { run_with(With_stream_detection()); } Don't use ?: when you really mean an "if" statement. Don't use the comma operator when you really mean two successive statements. There can be rare cases when they are a neat choice - but they are very rare. A key reason for this is that the details of ?: and the comma operator are not well known amongst many programmers. For example, for classes A and B, the expression "A(), B()" will create anonymous temporaries of the two types. But do you /know/, beyond any doubt, that the temporary A object will still be alive when B is created? The answer is that it will - but it is not obvious to many C++ programmers. (However, your "_" trick for converting to a common type was interesting. The naming could be improved, but it was a neat trick.) |
Juha Nieminen <nospam@thanks.invalid>: Jun 27 10:59AM > used in the same :?-expression: > (args[1] == "--faux-text"? With_faux_text{}._ : > With_stream_detection{}._), app::run(); I thought that there would be a simple explanation for that oddity, but it appears that it's, indeed, used for even more obfuscation. Even an experienced C++ programmer is going to have to examine that expression for a while before he understands what's going on. That's not good programming style. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 01:10PM +0200 On 27.06.2018 09:36, David Brown wrote: > run_with(With_stream_detection()); > } > Don't use ?: when you really mean an "if" statement. The choice operator is in the language for a purpose, which happens to be the exact purpose of the code. > Don't use the > comma operator when you really mean two successive statements. In the presented code only a single statement will do. If the comma is replaced with a ';', then cleanup will be performed be the call to app::run() instead of after. > There > can be rare cases when they are a neat choice - but they are very rare. This is one. ;-) > the two types. But do you /know/, beyond any doubt, that the temporary > A object will still be alive when B is created? The answer is that it > will - but it is not obvious to many C++ programmers. It better be. But it's an interesting debate: at what level of knowledge of details can one put the lines between "C++ expert", "C++ programmer" and "programmer sometimes using C++"? I think the line between expert and just programmer is somewhere where the programmer knows the rules of temporaries, that knowing that basic thing does not qualify as expert. > (However, your "_" trick for converting to a common type was > interesting. The naming could be improved, but it was a neat trick.) Thank you. :) Cheers! - Alf |
boltar@cylonHQ.com: Jun 27 11:34AM On Wed, 27 Jun 2018 13:10:17 +0200 >> Don't use ?: when you really mean an "if" statement. >The choice operator is in the language for a purpose, which happens to >be the exact purpose of the code. Its purpose is to return 1 of 2 possible values, not to replace a multi command "if" block. Having seen your example code in a number of your posts I think its safe to classify you as a showboating coder - ie you deliberately obfuscate your code simply to try and convince everyone how clever you are. However if you try and be too clever you can end up looking like a fool who doesn't understand the concept of appropriate use. Your asinine "auto main() -> int" in another post was a classic example of this. >and "programmer sometimes using C++"? I think the line between expert >and just programmer is somewhere where the programmer knows the rules of >temporaries, that knowing that basic thing does not qualify as expert. IMO a C++ expert is someone who cares more about the language than he does about actually solving problems. Most of us learn enough to get the job done and pick up more along the way from other peoples code. Very few read stroustrup from cover to cover mainly because we're too busy doing the job we're paid to do and have better things to do at home. Similarly I doubt you'd get many painters obsessing about their paint brushes, they're more concerned with the painting. |
Juha Nieminen <nospam@thanks.invalid>: Jun 27 12:19PM > Having seen your example code in a number of your posts I think its safe to > classify you as a showboating coder - ie you deliberately obfuscate your code > simply to try and convince everyone how clever you are. "Don't be clever" - Bjarne Stroustrup He further clarifies: "My point was to discourage overly clever code because "clever code" is hard to write, easy to get wrong, harder to maintain, and often no faster than simpler alternatives because it can be hard to optimize." |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 02:36PM +0200 On 27.06.2018 14:19, Juha Nieminen wrote: > "clever code" is hard to write, easy to get wrong, harder to maintain, and > often no faster than simpler alternatives because it can be hard to > optimize." I didn't see Boltar's comment because he's in my kill file. And you're pretty close now, again. Just a heads up. - Alf |
David Brown <david.brown@hesbynett.no>: Jun 27 02:46PM +0200 On 27/06/18 13:10, Alf P. Steinbach wrote: >> } >> Don't use ?: when you really mean an "if" statement. > The choice operator is in the language for a purpose, Yes it is. > which happens to > be the exact purpose of the code. No it isn't. The choice operator is part of C so that you can write things like: x = (a < b) ? b : a; It is part of C++ because it is part of C. It is certainly /not/ part of the C++ language so that you can use it to do different things by using constructors for different classes. That use is allowed because it would be complicated to disallow it, not because it is a good idea. >> Don't use the >> comma operator when you really mean two successive statements. > In the presented code only a single statement will do. Logically, you meant two statements. Define a variable (from one of your classes), then run the app. There are lots of things you /can/ do in C or C++ - and often you can use expressions for things that are logically separate statements. In a fair amount of code you could replace many of the ";" with commas. No one does, because it would be pointlessly confusing and non-idiomatic. > If the comma is replaced with a ';', then cleanup will be performed be > the call to app::run() instead of after. It would in this particular case - but not if you wrote the code in a more normal structure. Your code is an interesting example of using obscure syntax - but it is not a good way to write code. >> There >> can be rare cases when they are a neat choice - but they are very rare. > This is one. ;-) No, it is not - except from the viewpoint that it is an interesting example. If your purpose was merely to investigate or illuminate such possibilities, then it was clearly a good choice - if it was to write good clear code, it failed. > and "programmer sometimes using C++"? I think the line between expert > and just programmer is somewhere where the programmer knows the rules of > temporaries, that knowing that basic thing does not qualify as expert. Ah, there we can agree - an interesting debate could be made from this. At what point do you restrict your coding to make it easier to understand for a wider proportion of programmers? Or do you write code in a more advanced way, and restrict the programmers who work with it? (In this case, there is nothing to be gained - except a talking point and perhaps a little knowledge - from using an obscure structure. So here a simpler structure would be better.) >> (However, your "_" trick for converting to a common type was >> interesting. The naming could be improved, but it was a neat trick.) > Thank you. :) Your next challenge is to re-write it using a std::variant as a way of combining the two distinct classes :-) |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 03:06PM +0200 On 27.06.2018 14:46, David Brown wrote: > Your next challenge is to re-write it using a std::variant as a way of > combining the two distinct classes :-) That's good, I didn't think of that. But it's a library solution to what the core language already offers for this case. I don't think the ?: syntax is obscure; on the contrary, it's basic, while `std::variant` gets into the more advanced territory, as I see it. Cheers!, - Alf |
MrBoltarToYou@galactic.com: Jun 27 01:41PM On Wed, 27 Jun 2018 14:36:19 +0200 >> often no faster than simpler alternatives because it can be hard to >> optimize." >I didn't see Boltar's comment because he's in my kill file. Thats easily fixed as you can see. And the fact that you've killfiled me demonstrates that you're not only a show off, but have a fragile ego too and can't handle valid criticism. I hope I never have the misfortune to have to use any code you wrote. >And you're pretty close now, again. I'm sure he's quakeing in his boots. |
David Brown <david.brown@hesbynett.no>: Jun 27 04:02PM +0200 On 27/06/18 15:06, Alf P. Steinbach wrote: > this case. > I don't think the ?: syntax is obscure; on the contrary, it's basic, > while `std::variant` gets into the more advanced territory, as I see it. The ?: operator itself is standard, but unusual (compared to the other operators) and programmers are often less familiar with it. In simple cases it is common enough - for the sort of usage you have here, it /is/ obscure. It would also be banned by any decent coding standard - you never allow short-circuit expressions that have side effects. So you don't allow "A && B" if B has a side-effect - you write "if (A) { B; }". The same goes for || and ?:. Of course std::variant is advanced - it is C++17, and thus not available (much less familiar) to many programmers. It was merely a suggestion of an alternative idea for this sort of code - not because I thought it would be a /good/ way to write it. Writing fancy code like this can be a fun exercise, as long as you don't mistake it for /real/ code. Being "smart" can help people learn and give new ideas. Writing it in actual serious code is "smart-arse", which is no longer a complement. It's like using Greek letters as extra operators in C++ classes - it's fun, but highly unlikely to be good coding practice. And since people have been giving quotations, don't forget this one: "Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? " (Brian Kernighan) |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 27 10:21AM -0400 On 06/27/2018 07:10 AM, Alf P. Steinbach wrote: >> } >> Don't use ?: when you really mean an "if" statement. > The choice operator is in the language for a purpose, ... Correct. In C, it allows you to do something that otherwise requires multiple statements in a single expression. It should only be used when multiple statements are disallowed, such as initializers, or conditions in #if directives or if(), while(), do while(), and for() statements, or the first and third parts of a for(). Even in those locations, it should only be used if it's actually clearer than the alternative (which would, generically, involve defining a function that contains those multiple statements). It's in C++ for backwards compatibility, but C++ provides a number of alternatives that render it less necessary. > ... which happens to > be the exact purpose of the code. Incorrect. As a general rule in C++, anytime you might be tempted to write an if() or switch() statement that is that is directly or indirectly connected to a type, you should consider the possibility of using function overloading or inheritance and a virtual member function. I think that's precisely the right solution in this case. This also applies if you find yourself writing multiple catch() blocks for the same try{} block, which is explicitly type-based. >> Don't use the >> comma operator when you really mean two successive statements. > In the presented code only a single statement will do. Which could call an overloaded function or a virtual member function. >> There >> can be rare cases when they are a neat choice - but they are very rare. > This is one. ;-) No, it isn't. |
Manfred <noname@invalid.add>: Jun 27 06:03PM +0200 On 6/27/2018 3:06 PM, Alf P. Steinbach wrote: > this case. > I don't think the ?: syntax is obscure; on the contrary, it's basic, > while `std::variant` gets into the more advanced territory, as I see it. You may want to keep the ?: with a std::variant :-) Posting the code because I am not 100% confident that move ctors are guaranteed not to be called - I'm thinking of potential move of the std::variant. ============ #include <iostream> #include <string> #include <variant> class With_faux_text { public: With_faux_text(With_faux_text&&) { std::cout << "move With_faux_text" << std::endl; } With_faux_text() { std::cout << "ctor With_faux_text" << std::endl; } ~With_faux_text() { std::cout << "dtor With_faux_text" << std::endl; } }; class With_stream_detection { public: With_stream_detection(With_stream_detection&&) { std::cout << "move With_stream_detection" << std::endl; } With_stream_detection() { std::cout << "ctor With_stream_detection" << std::endl; } ~With_stream_detection() { std::cout << "dtor With_stream_detection" << std::endl; } }; using StreamContext = std::variant<std::monostate, With_faux_text, With_stream_detection>; class App { public: static void run() { std::cout << "App::run()" << std::endl; } }; StreamContext createContext(int argc, char* argv[]) { return (2 <= argc && std::string(argv[1]) == "--faux-text") ? StreamContext{std::in_place_type<With_faux_text>} : StreamContext{std::in_place_type<With_stream_detection>}; } int main(int argc, char *argv[]) { StreamContext context = createContext(argc, argv); App::run(); } ============== ./a.out --faux-text ctor With_faux_text App::run() dtor With_faux_text |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 09:45PM +0200 > snip Your third identify to be killfiled by me. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 10:54PM +0200 On 27.06.2018 16:02, David Brown wrote: > operators) and programmers are often less familiar with it. In simple > cases it is common enough - for the sort of usage you have here, it /is/ > obscure. How can a single ?: be obscure? Beginners learn it, very early on, and you say some experienced programmers you've encountered find it challenging? I find that claim hard to believe. > never allow short-circuit expressions that have side effects. So you > don't allow "A && B" if B has a side-effect - you write "if (A) { B; }". > The same goes for || and ?:. Yes, it's /generally/, often, maybe even usually, a Bad Idea™ to express side effects with boolean operators, because if anything else isn't evident, one expects such an expression to just compute a boolean value. But 1. it isn't /always/ bad to do that with boolean expressions, and 2. a choice expression isn't like a boolean expression. Regarding (1), in C++ the core language features are often just used to implement higher level features that we know from other languages. E.g. preprocessor directives and conventions about filenames and contents, are used to implement modules. In that spirit shortcut boolean expressions are sometimes used to implement bail-out from a sequence of operations that indicate success/failure via boolean returns: // A. OK for me const bool success = a() and b() and c() and d() and e(); which would be banned by your "decent coding standard", instead of the more complex exception based code // B. Gah! bool success = true; try { a(); b(); c(); d(); e(); } catch( exception const& ) { success = false; } or the code that a literal interpretation of what you write, would yield: // C. Double gah, kill me. bool success = a(); if( success ) { success = b(); if( success ) { success = c(); if( success ) { success = d(); if( success ) { success = e(); } } } } Again, compare that to // OK for me const bool success = a() and b() and c() and d() and e(); So "It would also be banned by any decent coding standard - you never allow short-circuit expressions that have side effects." appears to mean that the coding standards that you regard as decent, require the fantastic ugliness and awkwardness of (B) or (C) above. Regarding (2), that a choice expression isn't like a boolean expression, choice expressions are IME much more commonly used for side effects than boolean expressions are, especially where a result value is used. > (much less familiar) to many programmers. It was merely a suggestion of > an alternative idea for this sort of code - not because I thought it > would be a /good/ way to write it. Yes, considering all possibilities is often useful. If for nothing else, one might learn something from the exercise. :) > mistake it for /real/ code. Being "smart" can help people learn and > give new ideas. Writing it in actual serious code is "smart-arse", > which is no longer a complement. I don't get what's fancy or "smart" about it. Exactly what is fancy? Is it the conditional expressions? Do the programmers you know have problems with conditional expressions? > It's like using Greek letters as extra > operators in C++ classes - it's fun, but highly unlikely to be good > coding practice. But what is it that's Greek to you, or that you suspect would be Greek to most others, in the code? I see nothing but basics: RAII, conditional, comma expression. Easy peasy. > "Everyone knows that debugging is twice as hard as writing a program in > the first place. So if you're as clever as you can be when you write it, > how will you ever debug it? " (Brian Kernighan) As a counter example, the reason that we (C++ programmers) use RAII isn't because RAII is easier to debug than plain if-else's and sequences and `goto` a common cleanup. We use it because it's easier to understand and analyze, to prove correctness of, due to the simple guarantees. I am not sure about the debuggability of the code as I wrote it, though. Maybe the ?: expression and comma expression should be written with each part on its own line, maybe that would help a debugger show what's being executed. That research will have to wait though (for me)... Cheers!, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 10:56PM +0200 On 27.06.2018 16:21, James Kuyper wrote: >>> can be rare cases when they are a neat choice - but they are very rare. >> This is one. ;-) > No, it isn't. Well, let's compare your virtual member function code to the one I presented, when the codes do the same with same exception guarantees. Cheers! - Alf |
ram@zedat.fu-berlin.de (Stefan Ram): Jun 27 08:29PM Tools like Doxygen copy the head of a function definition to double as documentation: Synopsis int f(); , and, of course, the "Synopsis" gives us the return type. But what about a function definition like: auto f(){ return 7; } ? A synopsis like Synopsis auto f(); is hardly helpful. So should we avoid the auto return type for functions which are part of an API for this reason? |
ram@zedat.fu-berlin.de (Stefan Ram): Jun 27 08:37PM >It's in C++ for backwards compatibility, It allows you to directly transcribe a "mathematical" definition like .- | n * f( n - 1 ), if n is not 0 f( n ) = < | 1, , otherwise. '- which becomes n ? n * f( n - 1 ): 1 , and it allows you to express your ideas in code when you happen to think in terms of a case discrimination as shown. "Express ideas directly in code" - C++ Core Guidelines |
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jun 26 08:50PM -0700 On 6/26/2018 7:06 AM, Rick C. Hodgin wrote: > examine the headers. I post only from Eternal September or Google > News, and from Indianapolis, IN. > The imposter here posted from an "en-GB" timezone using Giganews. I hope all of the mimicry could be halted sometime.... |
Lynn McGuire <lynnmcguire5@gmail.com>: Jun 26 09:01PM -0500 "Modern C++ for C Programmers: part 1" https://ds9a.nl/articles/posts/c++-1/ Lynn |
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