- "²" - stray '\262' in program - 1 Update
- Union of bitfields and larger type on ARM - 3 Updates
- String integer id - 5 Updates
- C++ complex.h protability - 4 Updates
- TDD can be useful even when it doesn't achieve what you want - 8 Updates
- Reverse Iteration Fractal Encryption... - 3 Updates
- VS 2015 refactoring test results - 1 Update
Vir Campestris <vir.campestris@invalid.invalid>: Feb 23 09:42PM On 21/02/2016 21:15, Alf P. Steinbach wrote: > Oh, they're C++11 user defined literals. <snip> > Cheers & hth., It helps a lot. Thanks! Shame I'm writing a lot of C these days... Andy |
bitrex <bitrex@de.lete.earthlink.net>: Feb 23 02:17PM -0500 Does anyone know if the following "naughty" (implementation dependent) construct would work "correctly" on the ARM Cortex M4, compiled with arm-gcc-embedded? typedef union { uint32_t phase_accumulator_full; struct { uint8_t integer_high : 8, integer_low : 8, frac_high : 8, frac_low : 8; }; } phase_accumulator; |
John Devereux <john@devereux.me.uk>: Feb 23 07:36PM > frac_low : 8; > }; > } phase_accumulator; I am not an expert (ask on comp.arch.embedded) but my understanding is that this sort of thing is guaranteed by the EABI (bugs aside). -- John Devereux |
David Brown <david.brown@hesbynett.no>: Feb 23 10:34PM +0100 On 23/02/16 20:36, John Devereux wrote: >> } phase_accumulator; > I am not an expert (ask on comp.arch.embedded) but my understanding is > that this sort of thing is guaranteed by the EABI (bugs aside). I can't even figure out why it would be considered "naughty" at all. The only implementation-dependent aspects I can see are the alignment of the parts (on the ARM, 8-bit, 16-bit and 32-bit types all have "natural" alignments), and the ordering of the bitfields (which is low bits first - guaranteed by the ARM EABI, and thus consistent across compilers). |
Jerry Stuckle <jstucklex@attglobal.net>: Feb 23 11:21AM -0500 On 2/23/2016 9:43 AM, David Brown wrote: > No, the post here was /not/ what I expect from people in this group - > that is why I react against it. I don't think it really counts as > trolling either. I am not sure /what/ it counts as, but I don't like it. It is trolling, plain and simple, according to the commonly used definition for the last 20+ years. As are twisting people's words, ignoring facts someone else posts and other things I've seen in this group. Maybe you don't think it's trolling. But this post does not surprise me in the least. And the poster was even too chicken to use his own name. Just another proof of trolls being here. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
Paavo Helde <myfirstname@osa.pri.ee>: Feb 23 06:23PM +0200 On 23.02.2016 10:16, David Brown wrote: > But such checks are not constant expressions - you cannot use the result > in things like static initialisers, constexpr expressions, static > asserts, #if directives, etc. Are these constexpr limitations (like banning reinterpret_cast) there because of cross-compilation? Is it that if reinterpret_cast were allowed in constexpr, the compiler would need to emulate the target processor, whereas by current rules it only has to calculate the correct portable value? |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 23 07:15PM +0100 On 23.02.2016 09:01, Paavo Helde wrote: > possible to reuse the user literal mechanism itself, even if it is not > good for finding out the actual endianness it should be good for the > user literals themselves. If that were possible then it could serve as a way to determine endianness, which would be great. > (Warning: I do not have access to any big- or mixed-endian machines for > testing, so this may contain bugs, and certainly it can be simplified): I suspect that this is a late-night posting. I sometimes do that. ;-) Happily the net is full of critics. > } > } > } Okay, let's first examine constexpr uint64_t operator""_idraw(const char* p, size_t n) { return static_cast<unsigned char>(*p) | (n>0 ? operator""_idraw(p+1, n-1): uint64_t(0))<<8; } constexpr uint64_t SelectByte(int pos) { return pos==0 ? "\xff"_idraw : (pos==1 ? "\x00\xff"_idraw : (pos==2 ? "\x00\x00\xff"_idraw : (pos==3 ? "\x00\x00\x00\xff"_idraw : (pos==4 ? "\x00\x00\x00\x00\xff"_idraw : (pos==5 ? "\x00\x00\x00\x00\x00\xff"_idraw : (pos==6 ? "\x00\x00\x00\x00\x00\x00\xff"_idraw : (pos==7 ? "\x00\x00\x00\x00\x00\x00\x00\xff"_idraw : 0))))))); } This can be replaced with just constexpr uint64_t SelectByte(int pos) { return (pos >= 8? 0 : uint64_t( 0xFF ) << 8*pos); } That's a good code transformation, I think. :) Then this: constexpr uint64_t Fill64(uint64_t c) { return c | c<<8 | c<<16 | c<<24 | c<<32 | c<<40 | c<<48 | c<<56; } constexpr uint64_t SelectByte(int pos) { return (pos >= 8? 0 : uint64_t( 0xFF ) << 8*pos); } constexpr uint64_t IdFromString(const char* p, size_t n, int pos) { return (Fill64(static_cast<unsigned char>(*p)) & SelectByte(pos)) | (n>0 ? IdFromString(p+1, n-1, pos+1) : uint64_t(0)); … can be replaced with just constexpr auto left_shifted( unsigned char const val, int const distance ) -> uint64_t { return (distance >= 64? 0 : uint64_t( val ) << distance); } constexpr uint64_t IdFromString(const char* p, size_t n, int pos) { return left_shifted( *p, 8*pos ) | (n>0 ? IdFromString(p+1, n-1, pos+1) : uint64_t(0)); } And at this point it's clear that the code does an endian-agnostic conversion from a base 256 number specification, to number, just as the earlier programs. • • • The endianness issue can instead be addressed in the `StrFromId` function, where one is not constrained by the `constexpr` limitations. E.g. a strategic little call to `std::reverse` will do the trick. Cheers!, - Alf |
Paavo Helde <myfirstname@osa.pri.ee>: Feb 23 09:40PM +0200 On 23.02.2016 20:15, Alf P. Steinbach wrote: >> (Warning: I do not have access to any big- or mixed-endian machines for >> testing, so this may contain bugs, and certainly it can be simplified): > I suspect that this is a late-night posting. No, this was an early-morning posting before sufficient coffee intake ;-) > And at this point it's clear that the code does an endian-agnostic > conversion from a base 256 number specification, to number, just as the > earlier programs. Yeah, I was having a growing suspicion of the same ... > The endianness issue can instead be addressed in the `StrFromId` > function, where one is not constrained by the `constexpr` limitations. True, but I think someone wanted to see the strings in memory while debugging. But for that purpose the endianness is in practice easily detected by the relevant macros and in the remote chance the program gets it wrong then it is easy enough to fix and recompile. Anyway, thanks for demolishing my monster! Paavo |
David Brown <david.brown@hesbynett.no>: Feb 23 10:29PM +0100 On 23/02/16 17:23, Paavo Helde wrote: > allowed in constexpr, the compiler would need to emulate the target > processor, whereas by current rules it only has to calculate the correct > portable value? I don't know. I suspect it is more of a historical limitation - there are many things that a modern compiler can calculate at compile time, which early compilers could not do. If something is legal as a constant expression, then any compiler, even an unsophisticated and unoptimising one, has to figure it out at compile time - otherwise you would end up with code that was legal on one compiler and illegal on another one. I suppose the standards /could/ say "whether an expression using a reinterpret_cast is a constant expression or not is implementation dependent", but I think that would add a good deal of complications to the language. But Jerry is going to show us a compile-time constant expression to detect endianness using pure standard C++, so that will settle the matter. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 23 07:45PM +0100 On 23.02.2016 10:55, bartekltg wrote: >> There is a C++ standard library header <complex>. It's different from >> <ccomplex> and <complex.h>. > It has changed ;-) No. Not as far as I know. :) > "26.4.11 Header <ccomplex> [ccmplx] > 1 The header behaves as if it simply includes the header <complex>." Points to understand the above quote, which is of C++11 §26.4.10/1: • The header <ccomplex> is not the header <complex>. • The header <ccomplex> is the basic C++ variant of the /C header/ <complex.h>. It places the C declarations in namespace std. It may also place them in the global namespace. • The /C++ header/ <complex.h>, distinct from the C header <complex.h> (same name, yes), is defined in terms of <ccomplex> instead of directly in terms of the C header. The C++ header <complex.h> provides the same contents as <ccomplex> except that it provides this content in the global namespace. It may also provide the contents in the std namespace. And yes, I agree, the complexity of this is really ridiculous. The original C++98 idea was evidently to not-so-subtly-at-all encourage a move from "foo.h" headers to header names without filename extensions "cfoo". At that time C++ <ccomplex> was not allowed to pollute the global namespace. But that did not sit well with compiler vendors, who saw no reason to jump through hoops with additional extreme complexity, with no evident advantage other than maybe supporting some idealistic notions about filenames, so with C++11 the rules were changed to make the <ccomplex> and <complex.h> requirements symmetric (and ditto for all other such header pairs), incidentally making the whole thing /meaningless/. So, just include <complex.h>, and forget about the <ccomplex> complexity, so to speak – but remember that this is the /C++ version/ of <complex.h>, and so it can, at the implementation's discretion, make code that uses std:: qualifications compile, even though that will not compile with some other compiler. :( Relevant: C++11 §17.6.1.2: <quote> Except as noted in Clauses 18 through 30 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in the C standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C ++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3). </quote> > (4.5) — reinterpret_cast<cv T*>(a)[2*i + 1] shall designate the > imaginary part of a[i]. > " Yes. That compatibility is the whole point of the above wording. > I think the problem is with libraries based on fortran (with C > interface). Then reinterpreted cast is needed, but at least > should work. Oh. I didn't think of that. Cheers!, - Alf |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 23 07:55PM +0100 Oh, please disregard that posting, I was not thinking clearly. There is no way there can be a C++ version of C99 <complex.h>, due to the C99 keyword _Complex. :( Cheers, - Alf On 23.02.2016 19:45, Alf P. Steinbach wrote: |
bartekltg <bartekltg@gmail.com>: Feb 23 08:41PM +0100 On 23.02.2016 19:45, Alf P. Steinbach wrote: >>> <ccomplex> and <complex.h>. >> It has changed ;-) > No. Not as far as I know. :) In gcc 5.2.1, ccomplex: #pragma GCC system_header #ifndef _GLIBCXX_CCOMPLEX #define _GLIBCXX_CCOMPLEX 1 #if __cplusplus < 201103L # include <bits/c++0x_warning.h>
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment