- static constexpr in a class - 5 Updates
- for ... else blocks - 3 Updates
- Why do some people hate namespace prefixes? - 7 Updates
- Auto-incrementing or auto-decrementing values at compile-time - 7 Updates
- special string-implementation - 3 Updates
David Brown <david.brown@hesbynett.no>: Apr 21 10:03AM +0200 > I don't really see the point of these syntatic games that constexpr allows. > If its a constant expression then by definition you know the value when you > write the code so why not just have "static const int one = 1"? Obviously the real functions here are not as simple as "x + 1". |
David Brown <david.brown@hesbynett.no>: Apr 20 04:05PM +0200 On 20/04/2019 14:53, Alf P. Steinbach wrote: >> works fine, but it splits up the definitions in a way that didn't fit >> the flow of the code I was writing. > First, consider using `std::next` ;-) It's getting steadily harder to pick names that don't coincide with the standard library! It's just an example function name - no relation to std::next. > constexpr const int one = next(0); > constexpr int next(int x) { return x + 1; } > This reproduces the problem with ordinary functions. It's invalid code. Yes, that is because you are trying to use the constexpr function (to initialise "one") before it is defined. > It's a nice view, it explains most everything that can baffle a novice > about in-class-definition member functions. I didn't know that it also > explains `constexpr` member behavior. Thanks. That sounds like a way to understand the rules. In my case, the constexpr is actually fully defined before it is used - but because it is in a class that is not yet completed, the function definition is not considered complete either. I can appreciate that that this might not be the case. In particular, functions that depend on the class itself could not be considered "fully defined" until the class is fully defined - data members could be added after the definition, for example. So perhaps the rules of when the functions can be used are made to give a simple and consistent view, rather than a more complex set of rules about what is and is not allowed. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 20 04:42PM +0200 On 20.04.2019 16:05, David Brown wrote: > In my case, the constexpr is actually fully defined before it is used - > but because it is in a class that is not yet completed, the function > definition is not considered complete either. I don't buy that as a technical explanation, and I don't think it's a good conceptual view (because it doesn't explain anything else, it's just a special case arbitrary rule). The ordinary conceptual view of a compiler's rewrite where it moves the member function definitions to after the class, fits too well. That is, it fits everything I know. > So perhaps the rules of when the functions can be used are made to give > a simple and consistent view, rather than a more complex set of rules > about what is and is not allowed. Yes. Cheers!, - Alf |
blt_q7_a8fplu@0gkdzjla5uk04q8c.com: Apr 22 09:53AM On Mon, 22 Apr 2019 11:33:48 +0200 >The code below is originally from C, rather than C++, simply augmented >by "constexpr". Even with optimisation disabled, a C++14 compiler must >calculate the CRC check here at compile time. Or not even in 2017 mode.... fenris$ c++ -v Apple LLVM version 10.0.1 (clang-1001.0.46.4) Target: x86_64-apple-darwin18.5.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin fenris$ c++ -std=c++17 test.cc test.cc:49:24: error: constexpr variable 'c' must be initialized by a constant expression constexpr uint8_t c = crcData8(0, s, sizeof(s)); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ test.cc:42:40: note: read of non-constexpr variable 's' is not allowed in a constant expression crc = crcTable8[crc ^ (*pData++)]; ^ test.cc:49:28: note: in call to 'crcData8(0, &s[1], 13)' constexpr uint8_t c = crcData8(0, s, sizeof(s)); ^ 1 error generated. Whoops. |
blt__k4yrjhiu@dmq3k.co.uk: Apr 21 10:15AM On Sun, 21 Apr 2019 10:03:01 +0200 >> If its a constant expression then by definition you know the value when you >> write the code so why not just have "static const int one = 1"? >Obviously the real functions here are not as simple as "x + 1". They're never going to contain anything more than simple arithmetic formulas if the output can be computed at compile time so why not just make them a const. |
Bart <bc@freeuk.com>: Apr 18 09:15PM +0100 On 18/04/2019 20:36, Ben Bacarisse wrote: > since multi-level breaks are rare and likely to be flagged by a big > comment, but the label is in just the right place for me to know I have > to think about gotos. In my codebase (only compiled code not scripting), about 2.5% of all 'breaks' are multi-level ones (and break is used very commonly in my code to terminate endless loops), and 2% of all 'for' loops are 'for-else'. It doesn't sound much, but DB mentioned once that only 1.5% of his C for-loops were anything other simple iteration via a variable. Yet C loops still allow all those other possibilities, things that can make code harder to reason about, not easier. |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Apr 18 08:36PM +0100 > ... If writing C, then every so often you have to stop and work around > the problem of C having only single-level breaks. This is a case where what you call a work-around, I call an improvement. I like to reason about code, and the label helps a lot. I often ask, particularly after loops, "what is the state of the program at this point?" and the presence of a label is a big red flag telling me I have to take partial execution into account. It's not a huge advantage, since multi-level breaks are rare and likely to be flagged by a big comment, but the label is in just the right place for me to know I have to think about gotos. -- Ben. |
Bart <bc@freeuk.com>: Apr 18 06:54PM +0100 On 18/04/2019 11:21, David Brown wrote: > a lambda), or using a goto ? > If your language already has a "for/else" statement, then it's fair > enough to use it, of course. Well, this is the point really. If a feature is reliably available, then you just use it because it's convenient. Instead of inventing a solution or rewriting a pattern you've used 100s of times before. Same argument with the subject of multi-level loop breaks. If writing C, then every so often you have to stop and work around the problem of C having only single-level breaks. (Or zero-level breaks if you happen to be inside 'switch'.) (Last time I used a multi-level break: about 15 minutes ago. I wasn't writing C. It's just there. What I could also have done with actually was 'while-else' that I haven't got. So something to ponder adding.) |
Chris Sykes <chris@amtiskaw.net>: Apr 22 10:43AM +0100 On 21/04/2019 13:37, Juha Nieminen wrote: > undrestandability of code shouldn't be reliant on an IDE. The code > should remain readable and understandable even if you are just looking > at it with a vanilla text editor. Absolutely. Time saved in code review (or just coming back to some code *you* wrote a while ago) vastly outweighs a few characters saved when first entering the code, and both IDEs and editors tend to have pretty good auto-complete when entering code these days anyway. |
scott@slp53.sl.home (Scott Lurndal): Apr 19 06:21PM >> foo::string or bar::string was intended. >Why are those other modules also defining 'string'? Which is known to be >a built-in type. Perhaps because the code was written long before there was a concept of namespaces (or a class called 'string') in C++? |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 21 04:30PM +0200 On 21.04.2019 14:50, Bart wrote: >> should remain readable and understandable even if you are just looking >> at it with a vanilla text editor. > Or on a printout, if anyone still uses those. That's what we have mobile phones for, when one sits down to read code on paper. Cheers!, - Alf |
Manfred <noname@add.invalid>: Apr 18 03:57PM +0200 On 4/18/2019 11:44 AM, Bart wrote: > to distinguish them from not only Martian rocks and wind, but from any > other planet? > How annoying would it be to have to do that all the time? The translated geography of "On Earth" would be "within std", i.e. inside standard-library code, not application code. |
Vir Campestris <vir.campestris@invalid.invalid>: Apr 18 09:36PM +0100 On 18/04/2019 15:09, Juha Nieminen wrote: > all the names in the library? That would only make your code harder to read > because you can't see anymore where you are calling the libpng library > functions and where you are calling something else. There are those who wish to remove the std:: prefix from all the names in STL. That's not really different to removing the png_ prefix from all the names in the PNG library. I asked this question on the C++ group at work. Early indications are that people want to keep the std:: prefixes in place. I'll try to report back... I think there are more people on that than regularly post here. Andy |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 18 10:39PM +0200 On 18.04.2019 16:12, Juha Nieminen wrote: > "shared_ptr" without a prefix. Which version is it using? > (This is from an actual real-life example, not just an artificially > invented one.) First note that you don't need to know. `std::shared_ptr` is an adaption of `boost::shared_ptr`, so you already know all about it even if you don't know details of Boost. Also if you're going to maintain that code, * use the smart pointer that the original developers did, unless you're going to refactor it, in which case you're in for a larger effort anyway. --- But let's say the example was, instead, something like `something::Image` versus `something_else::Image` versus `boost::gil::Image`, where the two first have nothing to do with photographic images. Ordinarily you get acquainted with the relevant types as you dive into the code. But if one just, unexpectedly, encounters an unqualified "Image", then one checks what that means in this code, once. The easiest way is just visual inspection, move eyeballs up with line of sight in roughly the direction of the nearest `using` declaration. If that's out of sight then I find it easier to hover the mouse over the word than to scroll. Cheers & hth., - Alf |
Bonita Montero <Bonita.Montero@gmail.com>: Apr 18 04:21PM +0200 > all the names in the library? That would only make your code harder to read > because you can't see anymore where you are calling the libpng library > functions and where you are calling something else. If there would be namespaces with libpng and the types / fuctions within this namespace would be meaningful and not ambigous when stripped, this could be convenient. With std:: the types and functins are well known to the deveopers so there isn't any confusion when std:: is stripped. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 18 04:45PM -0400 On 4/18/2019 4:37 PM, Ben Bacarisse wrote: >> } > This ties the correctness of every calling function into the order in > which these tests are written. You missed the part where the idea I'm looking for bakes the values first encountered with the naked #autodec into solid values which are later identified as #autodec[-1] ... #autodec[-Nn], which allows later #autodec portions to be added and they'll automatically insert the next value in that location. > I think it should be added to your language ASAP. You're such a hateful person to me, Ben. You said previously in a private email that you were going to try to refrain from responding to my posts. Please try harder. Your failures are unbecoming. -- Rick C. Hodgin |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 19 12:52PM -0400 On 4/19/2019 12:37 PM, Richard Damon wrote: > You have a magic number there and you need to dig into the documentation > to have any idea what that number means (there is nothing inherent in > the value -2 that tells you what the error would be). Got it. -- Rick C. Hodgin |
jacobnavia <jacob@jacob.remcomp.fr>: Apr 18 11:37PM +0200 Le 18/04/2019 à 22:07, Scott Lurndal a écrit : > function know, a priori, which return code matches which (pre)condition > failure; particularly when subsequently code gets inserted into the existing set > such that successive autogenerated return codes are shifted by one? And why are we discussing this brain-dead ideas from this known spammer? Why people here feel happy answering this kind of rubbish? Just looking at this kind of "proposal" for his vaporware leads a sane reader to deduce that: 1) The brain of the poster is malfunctioning badly. 2) He is just posting nonsense, vaguely related to C, to start "discussions" to cover up his spamming. > Just use a #define, static const uint32_t or enum and update them as needed. That would work, but you forgot something: Before coding (and also before posting rubbish) he should TURN HIS BRAIN ON... But apparently he can't. |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 19 09:25AM -0400 On 4/19/2019 9:13 AM, Richard Damon wrote: > This is NOT an operation that seems valid for a compiler, as the > compiler should NEVER go back and change the source code. I've had that thought, but I've also had the thought that the tools we use should be accommodating to the needs of some required syntax and operations at times. We shouldn't have to diversify very far for some features that are oft-used. I use that pattern in pretty much every function I write that is visible outwardly through an API. And it becomes tedious to have to manually set the values. Being as I code that way pretty much every day, it seems that it would be of benefit. > It might make sense for a developement platform (like an IDE). I can see that applying to specific things, like in Windows we have to make sure return handles are not set to the INVALID_HANDLE_VALUE constant, but that same constant isn't valid on other OSes... so there would be value there for having platform-dependent features added to the development platform. But for cases that transcend OS barriers, I think it would be more desirable to have a language-level solution. > need to add a new error code, I add an entry to the enum and return that > entry. This says that calling code has names for the various error > codes, rather than having to be littered with all the magic numbers. I am unaware of the rule of magic numbers. I think the ability to receive source code, and have it have a user- specified (in source code) request to assign something mechanically rather than manually, and then re-write the altered source code back out, is a desirable feature that the language should possess, especially when the language is recognizing that it's working in concert with a live developer who is coding at various times, and the compiler is not just seeing static code that is more or less stable from a mature code base. Having this new ability would allow us to introduce a slew of features which bake-in on the first compile, and are then viewed as constants after that. The machine would do it reliably, and we wouldn't have to get bogged down in defining extra minutia details. -- Rick C. Hodgin |
Joe Pfeiffer <pfeiffer@cs.nmsu.edu>: Apr 19 05:16PM -0600 > I can see doing this in an external tool, but is there some way to do > it in C/C++? > And if not, does anyone have any idea for a good syntax on how to do it? This really doesn't seem like a good idea to me. Not only are you using "magic numbers", you're using magic numbers you haven't defined yourself, and whose value will change if additional if's get added at some later time. I'd much rather use an enum and typedef typedef enum {SUCCESS, OOPS, FATAL_ERR, ...} ReturnCode; |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 18 03:51PM -0400 I have a need fairly often to return distinct values for a return value. I don't particularly care what the values are, but they just need to be distinct and unique so that if they are returned later I can identify the exact cause of the error, where it failed. Something like this: int my_function(void) { if (!test_condition1) return -1; // Indicate it failed at this test // Arbitrary code if (!test_condition2) return -2; // Indicate it failed at this test // Arbitrary code if (!test_condition3) return -3; // Indicate it failed at this test // If we get here, we're good } Is there an existing way in C/C++ to automatically create some value that would allow me to add a new test and have it inject the new value? Ideally, I'd like for the compiler abilities to be sticky, meaning once you put in the token/whatever to identify you need a locally scoped automatically incrementing or decrementing value, that it bakes it into source code during the compile. Something like coding it this way initially: int my_function(void) { if (!test_condition1) return #autodec; // Indicate it failed at this test if (!test_condition2) return #autodec; // Indicate it failed at this test if (!test_condition3) return #autodec; // Indicate it failed at this test // If we get here, we're good } And during compilation it automatically translates it to this for, baking in the number: int my_function(void) { if (!test_condition1) return #autodec[-1]; // Indicate it failed at this test if (!test_condition2) return #autodec_[-2]; // Indicate it failed at this test if (!test_condition3) return #autodec_[-3]; // Indicate it failed at this test // If we get here, we're good } This would allow new code to be added later without a hard-value, and it would automatically adjust to the value inside the scope: int my_function(void) { ==> if (!test_condition0) ==> return #autodec; // Indicate it failed at this test if (!test_condition1) return #autodec[-1]; // Indicate it failed at this test if (!test_condition2) return #autodec_[-2]; // Indicate it failed at this test if (!test_condition3) return #autodec_[-3]; // Indicate it failed at this test // If we get here, we're good } It would change to this during compile, and write the source file back out: if (!test_condition0) return #autodec[-4]; // Indicate it failed at this test I can see doing this in an external tool, but is there some way to do it in C/C++? And if not, does anyone have any idea for a good syntax on how to do it? -- Rick C. Hodgin |
scott@slp53.sl.home (Scott Lurndal): Apr 18 08:07PM >This would allow new code to be added later without a hard-value, and >it would automatically adjust to the value inside the scope: There are two sides to every function call - how do the callers of that function know, a priori, which return code matches which (pre)condition failure; particularly when subsequently code gets inserted into the existing set such that successive autogenerated return codes are shifted by one? Just use a #define, static const uint32_t or enum and update them as needed. |
Bonita Montero <Bonita.Montero@gmail.com>: Apr 20 10:22PM +0200 >> Yes, 1MB stack-size is very large. That would be consumend >> to a significant extent only when havin massive alloca()s. > Or your strings... Even if you end up allocating as much stack space through this kind of "stacticized" strings like in C this wouldn't blow up the stack to its maximum size. |
Bonita Montero <Bonita.Montero@gmail.com>: Apr 19 08:58PM +0200 >> template-parameter for the size of an an internal buffer which holds the >> string instead of allocating the content on the heap. > std::array<char,N>? Thats much less than the functionality I have in mind. >> grown beyond the limit) > Some string implementations have handling for fast in place storage for > short strings. Short stings woulf fit only for very short strings. >> a basic_string so this type of string would be incompatible. > Exactly. And converting strings over and over (with allocations) can be > much more impact than the optimization gain. There would be no additional conversions. > As long as there is no need to pass /mutable/ strings to library > functions the use of const char* is the least common denominator. Maybe, but there are other cases. Memory-allocation is simply slow. > It is quite easy to provide zero copy conversion operators to this > type for any string implementation. An overloaded += and other operatoes also wouldn't copy if the capacity would be suffient. |
Bonita Montero <Bonita.Montero@gmail.com>: Apr 20 10:37PM +0200 >> to a significant extent only when havin massive alloca()s. > You must be kidding. A random cat picture from the intertubes is likely > more than 1 MB nowaydays. You won't store this and everything in the size-magnitude of this on the stack. > More to the point, there are many problems which could be elegantly > solved by recursive algorithms in C++, but technically they cannot > because the hardware recursion depth is severely limited, ... This is not a practical boundary since you rarely allocate so much data per recursion-level on the stack. |
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