- Initialization of std::vector<std::string> throws - 4 Updates
- Substitution failure can be an error - 3 Updates
- [QT creator on "nix"] - getting a strict 8 bit (1 byte) array with no padding - 17 Updates
- How to write a helper function - 1 Update
| Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Nov 22 01:44PM On Fri, 22 Nov 2019 12:12:43 +0100 > problem.cc:4:8: note: candidate expects 1 argument, 2 provided > problem.cc:4:8: note: candidate: 'Foo::Foo(Foo&&)' > problem.cc:4:8: note: candidate expects 1 argument, 2 provided I do not have all the previous exchanges available so I may be repeating what others have said, but the reason why single braces fail is because you are passing two arguments to a conversion constructor of Foo taking one (or no) argument. As to why double braces work, my guess is that (ignoring elision) the inner braces perform an implicit conversion to std::vector<int> via std::vector's constructor taking an initializer_list, constructing a temporary vector with two elements in the vector, and that this then initializes Foo, using std::vector's move constructor. But as I say, that is a guess. |
| "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 22 04:30PM +0100 On 04.09.2019 14:20, Sam wrote: >> terminate called after throwing an instance of 'std::length_error' >> what(): basic_string::_M_create > Because this is undefined behavior. That's the short explanation, but it would be even more informative to mention why. Like, #include <iostream> #include <string> #include <vector> using namespace std; auto main() -> int { const auto& data = "Hello"; std::vector<std::string> v( {{&data[0], &data[4]}} ); std::cout << v.front() << "!" << endl; } Result: Hell! I.e. it uses the `string` constructor that takes two iterators. >> whereas neither >> std::vector<std::string> pt({{"One"}}); This looks like it would use the `string` constructor that takes a pointer to C string. > If you actually examine the end result the last declaration, you will > discover, to your surprise, a std::vector<int> with just one value, and > that would hopefully be a big honking clue as to what this is doing. No, this one is more tricky. Apparently it uses the move constructor of `vector` to take a temporary `vector` constructed from the inner braces as an `initializer_list`. Disclaimer: the results are consistent with this explanation, and there doesn't seem to be any other explanation, but I haven't debugged. > yourself in a foot. It would be nice if it did, and in many cases it > does; but you can't rely on your compiler to keep you from shooting > yourself in a foot. The problem is not the compiler or programmer. The problem IMO is some political shenanigans in the C++ standardization committee, where they chose to sabotage Bjarne's vision of uniform initialization by making initializer lists take precedence in overload resolution. I prefer this explanation of academics' childish evilness, to sheer incompetence at that level, because the explanation of incompetence is too frightening. The political view has so far, to my knowledge, yielded accurate predictions and postdictions. For example, the political view of childish sabotage indicates that the filesystem::path UTF-8 functionality /will/ be sabotaged for Windows in C++20, along with use of `u` prefix string literals. The `u` literals don't make much sense in pure *nix-specific code, because literals are UTF-8 encoded there anyway, and so the change in type doesn't matter much there. But in Windows, those unfortunate souls who have tried to embrace the UTF-8 world via `u` literals and filesystem::path, will have some work to do, including implementing their own UTF-16 to UTF-8 conversion for getting an UTF-8 representation of a path. - Alf |
| Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Nov 22 04:13PM On Fri, 22 Nov 2019 16:03:12 +0100 > Okay I guessed that much, but why can't the compiler do the latter when > there is only one pair of braces? The error message clearly indicates > that an initializer list is considered. That's because in the absence of an initializer-list constructor for Foo, the compiler is obliged to treat 'Foo f{4,5}' as a call to a constructor taking two arguments, and you haven't provided an initializer list constructor for Foo. The only constructors available are the user-provided constructor (which is a combined default constructor and conversion constructor), and the compiler provided copy constructor and move constructor. You will see that the compiler did consider these as candidates, and then (obviously) found no match. Leaving that aside, I think the main aim is to write intelligible code, not code which scratches at the margins of C++'s implicit conversions. So instead of writing 'Foo f{{4,5}}', write 'Foo f{std::vector<int>{4,5}}', and likewise with your vector of string. Or provide an initializer-list constructor. You will then be able to understand your intentions when you come back to it 6 months later. > figured out. So the two string element case fails only because the > compiler picks the wrong constructor. I find that odd because the > initializer list seems to be the more obvious choice… You have received a separate answer to that. |
| Ralf Goertz <me@myprovider.invalid>: Nov 22 12:12PM +0100 Am Wed, 4 Sep 2019 14:33:39 +0200 > > { { /* something */ } } introduces a braced initialization list with > > one value. > But didn't we need to use two braces for container intialization? Since nobody has explained that satisfactorily yet (also see Tim's answer to Pavel) and I just stumbled over it again, I'd like to follow up. In the following situation double braces are necessary. But why? This kind of problem led to my original belief that for containers they were always needed. #include <vector> #include <iostream> struct Foo { std::vector<int> v; Foo(std::vector<int> v_=std::vector<int>()) : v(v_){} }; int main() { Foo f{{4,5}}; //double braces needed for (auto r:f.v) std::cout<<r<<std::endl; return 0; } With single braces I get: problem.cc: In function 'int main()': problem.cc:10:14: error: no matching function for call to 'Foo::Foo(<brace-enclosed initializer list>)' 10 | Foo f{4,5}; | ^ problem.cc:6:14: note: candidate: 'Foo::Foo(std::vector<int>)' 6 | Foo(std::vector<int> v_=std::vector<int>()) : v(v_){} | ^~~ problem.cc:6:14: note: candidate expects 1 argument, 2 provided problem.cc:4:8: note: candidate: 'Foo::Foo(const Foo&)' 4 | struct Foo { | ^~~ problem.cc:4:8: note: candidate expects 1 argument, 2 provided problem.cc:4:8: note: candidate: 'Foo::Foo(Foo&&)' problem.cc:4:8: note: candidate expects 1 argument, 2 provided |
| Manfred <noname@add.invalid>: Nov 21 03:50PM +0100 On 11/21/2019 6:02 AM, Alf P. Steinbach wrote: > I remember introducing Bjarne to the term in a mail exchange, but it's > apparently not in my GMail so it must be have been before July 2006. > - Alf read: Bjarne's book says on SFINAE ... The C++ Programming Language (4th Edition), p. 692 However, it is curious that the following still fails: template< class Int, class UInt = make_unsigned_t<Int> > struct S { // using UInt = make_unsigned_t<Int>; UInt m; S( Int x, Int ): m( UInt( x ) ) {} }; The error is still about "invalid use of incomplete type", which sounds like a type error to me. while template< class Int, typename = typename enable_if<is_integral<Int>::value>::type struct S { using UInt = make_unsigned_t<Int>; UInt m; S( Int x, Int ): m( UInt( x ) ) {} }; seems to work fine. |
| David Brown <david.brown@hesbynett.no>: Nov 21 03:58PM +0100 On 21/11/2019 14:29, Öö Tiib wrote: >> them.) > I sometimes try programming languages (for fun puzzle with new tool) > so I'm 100% sure that all of those (plus also Kotlin) use "type right" syntax. I too like to try new languages - when I get the time! > Note that it is actually matter of taste (again) so your mileage may vary > from strongly disagree to fully agree but the argumentation felt relatively > solid there. I'll read it - thanks for the link. > My own opinion is that C's declarations are simpler for parsers to parse > but Go/Rust/Swift/Kotlin declarations feel easier for human to to type > and to read. Many of the humans here find C's declaration easy to parse from long habit - it's always difficult to judge such inherently subjective issues. |
| Vir Campestris <vir.campestris@invalid.invalid>: Nov 22 09:46PM On 19/11/2019 11:48, Alf P. Steinbach wrote: > But I would guess that any group of C++ programmers using deduced return > type is not yet large enough that there would be any herd followers. > - Alf That's interesting. That sound as if you're on my side of the "almost always auto" argument I've heard bandied about - not least by the guy who owns our coding standards :( The argument is that given "x=4.2" you _know_ that x is a double, there's no point in saying so. I don't like it - that variable ought to be a type you know, and you should say so. I find it easier to _read_ code that explicitly states the types. OTOH, I've experimented, and it's easier to _write_ code that uses auto everywhere. When I read "auto x = somefunction()" I don't know what x is. Unless I look at the declaration. Which if I'm unlucky is one of several overloads with template type deduction from the parameters. But IMHO reading matters more. You'll only write it once. Andy |
| Paavo Helde <myfirstname@osa.pri.ee>: Nov 21 06:20PM +0200 On 21.11.2019 13:53, Soviet_Mario wrote: >> I'm curious about something. Do you have a realistic expectation that >> your code might need to work under an implementation with CHAR_BIT > 8? > no, not at all. Good. I suspect that without lots of porting and testing efforts none of these software pieces would work with CHAR_BIT>8 - neither gambas, neither QT and neither your code. > code that calls the C++ static library and that expects a 8-bit wide > unsigned integral, find its matching type in the C++ code, as they need > to share bitmaps and transparency maps. This is easy, use unsigned char or std::uint8_t. > The bitmaps use 32-bit packed colors+alpha channel, so I was assuming no > difficulty in exchange. This is more tricky because the size of int or long varies much more than char. For example, long is 32 bits in 64-bit MSVC and 64 bits with 64-bit gcc on Linux. However, for your purposes std::uint32_t should work fine. > support for single bit R/W > so I decided to waste some space and to use an addressable unit of 8 > bits for a boolean value This is a common choice, ok. > static library solution would produce a binary with all the needed QT > essentials hard wired in it and no further dependencies (just a guess, > all to be verified). Qt is mostly a GUI library as far as I have understood. Of course it has all bells and whistles like threading support and datetime library and whatever, but these things are nowadays also present in standard C++. So if you are writing some back-end library with no GUI interface involved, you actually should not need Qt at all. |
| David Brown <david.brown@hesbynett.no>: Nov 22 11:40AM +0100 On 22/11/2019 10:37, Öö Tiib wrote: > Both gcc and clang have -Waddress-of-packed-member but AFAIK you > won't get that warning when compiling for platform on what it does not > matter. I wasn't saying that /I/ don't know the answer to these questions, or that other more experienced developers don't know. I was saying that that folks suggesting "pack" here don't know the answers. And that is what matters - they are recommending a technique that they do not fully understand. (If they did understand it fully, they would understand that it is completely unnecessary in this situation.) For the gcc warnings: "-Waddress-of-packed-member" warns when you take the address of a packed member, regardless of alignment and regardless of whether the target supports unaligned data. It is enabled by default. "-Wpacked" warns if you have made a struct "packed" but it does not affect the size or layout of the struct. ("packed" attribute will still affect the alignment of the struct.) It would trigger for code like the the packed "pixel" struct, since the "packed" attribute does not affect the structure. Another useful warning here is "-Wpadded", which will tell you if a struct has padding for alignment of members or the struct itself. If "-Wpadded" is not triggered for your structs, making them "packed" is not going to be at all useful (unless you need to change their alignment). >> full size, packed means you can get misalignments, which can have a very >> significant impact on efficiency in some situations. > Huh? Packed structs usually lead to raise of storage efficiency. No, they don't - not usually, not significantly, and not helpfully. /Occasionally/ they can help, but more often you can get close to the same efficiency by simply re-arranging the members more sensibly. (And if you don't have enough members to make this work, you don't have enough data for the memory efficiency to be relevant.) > Where we have to process large array of those there it is often impossible > to predict without profiling on target platform if that will cause performance > gain or loss. If memory efficiency or performance here is important, you would be better off having two arrays - one of doubles, one of chars. Sure, that would involve a little extra code - but C++ excels in letting you write wrappers so that you have a good clean interface while keeping the internal structures intact. And now you have all your doubles aligned, giving significantly better cache usage and access speeds, and allowing the possibility of SIMD vector instructions for massive improvements. And since a structure like this is typically for a "valid, value" pair, you now have 8 times the efficiency in dealing with invalid data over the array since you only need to access the big doubles when the data is valid. And if you only actually needed a single bit (bool) of the char, you could potentially get another factor of 8 here (depending on the ratio of valid to invalid values). Packed /can/ be useful, but very often it is used when it is unnecessary or directly detrimental, and often there are better ways to deal with the situation. |
| Soviet_Mario <SovietMario@CCCP.MIR>: Nov 22 07:35PM +0100 Il 22/11/19 15:04, David Brown ha scritto: >> sure I have no idea, I put the pragma there just for "precaution" >> what cost is that supposed to have ? > I've told you in several posts what the costs are. put is alas irregular verb : I meant its PAST form actually. I have abandoned the unsigned Bit_Field : 8 solution as soon as you (a lot of people) stated that u_int_8 MUST have exactly 8 bits. In that case either pragma is USELESS (and hence does not produce any reasonable effect, neither slowness), either is NECESSARY (and so the slowing effect is a unavoidable price that I MUST pay either) > "Packed" is /not/ a > "precaution", nor is using a struct with a bitfield instead of uint8_t. the second part has been abandoned early > If you don't know what you are doing I'm rather weak in higher level C++ constructs, and I know that, but not particularly so in low level (some couple of tens of years ago I used to stuff C code with inline "asm" statements or even __emit() calls). >, fine - if I understand you > correctly, you are experienced with gambas no, I am rather new to gambas actually. I was used to VB (Visual Studio, but not even recently). Going to Gambas has been actually a pain (not saying it is bad, absolutely not : it's me that knows much less than .net framework). On QT I am even more newby. > programming but new to C++. well, I am more of outdated than new, I had used C++ (and C) a lot in 1995-2000 roughly, then less and less afterwards. But strangely enough, I find it more easy to think in C++ terms when I met problems in basic. > So /ask/ (and please read the answers). Don't guess, or grab the first > thing that you find from a google search. but I DID follow the answers :) > And when the more experienced > people in a group like this all say "don't use packed" and "use > uint8_t", I didn't read or desume the two things should be mutually exclusive. Anyway, there are three scenarios 1) added pragma (to the four u_int_8 members in a struct) is USELESS, as the struct was just packed natively (and hence does not produce any reasonable effect, neither slowness), either 2) is NECESSARY, as the struct would not have been natively packed otherwise (and so the slowing effect is a unavoidable price that I MUST pay either) either 3) it is NOT SUFFICIENT (in this case, luckily unlikely, nothing would have worked fine at all) as for ALIGNMENT problem, I should not meet any I guess. The packed (natively or forcefully) struct is 32 bit wide, so allocating an array should allow nice addressing of any item even on a 64 bit OS And no item would cross critical addressing boundary > then that is what you should do. Ask /why/, and try to learn > - and once you do understand "pack", when it can be useful, when it is > useless, when it is worse than useless, If you have some further patience, tell me if the 3 scenarios fit the present situation (not a more general one, but just this) > what it does, and what it costs > - /then/ you can decide that because you know the full situation better > than we do, you still want to use it against general advice. I had given all details sufficient : the data layout is what I said, so no obscure aspects > "Packed" is not a precaution - I call it a precaution as it reduces the chances of a non packed data layout. I was not saying it would be successful necessarily in every scenario (even sizes sequence is relevant, and I know this, but my members were all 1 byte long) > have nothing better and know you can't write the code as well without > it. (That might mean you can't write the code as quickly or clearly > without it, which is fair enough - /if/ you are sure it is necessary.) let's say it explicitely if I have union { struct { u_int_8 Red, Green, Blue, Alpha; }; u_int_32 AllChannels; }; without PRAGMA, do I have any explicit or implicit warranty that my union be 32 bit long ? If so, PRAGMA is useless. If not, it seems it might be useful. what damages could PRAGMA PACK produce ? If the union would be just packed natively, I guess none. If it wasn't, at best it would pack it (and maybe slow it, but this is irrelevant, I need precise disk layout). At worsk it would be insufficient to actually pack it, so my problem is unsolved. In this last worst case, are there any other means of getting the thing to work ? What are them ? >> operations > Of course there is use in knowing this, if speed is an issue. If the > processing takes 1000 times as long as the loading and saving, this could be true only if load/store is "optimized" like I stated. If it was done an item at a time it would become very very slow (and depending on smartness of OS caching anyway, but not even so much even then, as I read/write the whole file, which can be 4-12 MB long and one time only, so caching cannot be as useful as when reusing a small region many times). > then you > know that putting the slightest effort into speed optimisation for file > access is a waste of effort when I made some elaboration all in gambas the times were "mixed" : some basic transformations with few or no floating point calculations went actually FASTER than disk read/write, with some more f.p. intensive calculations disk load/save were faster. But in any case, the same "order of magnitude", not 100-1000-etc times slower or faster. > shave 0.1% off the processing time than increasing the speed of the file > access by orders of magnitude. > And if your file format contains non-aligned members, why making general guess when I reported precisely the layout ? I said : 16 bit (width) - 16 bit (height) - N x 32 bit (R,G,B,alpha) where N = width x height = number of "pixels" every pixel is multiple of 32 address on file (but this seems irrelevant to me). In the ram layout, the BMP descriptor has width and height as "local" members, and a pointer to an array of struct aligned in memory by the NEW [] operator who is aware of alignment requirements. Where are the possible problems ? What problems are affected by a pragma pack directive ? > then the simplest > and easiest way to improve and simplify the code, and improve the speed > of several parts, is to fix the file format. that point is unmodificable. I strictly need full color and no compression. The alpha channel is maybe a bit overkill (255 level of transparency is more than needed ... but taking less is useless or impossible, and 1 byte is natural for the otherwise 3,sth bytes long struct) > Make sure the members are > aligned (add explicit dummy members if necessary) since when reading/writing files suffer from this ? Files are BYTE oriented internally (and the OS does caching independently and transparently, basing on disk cluster sizes but this is not sth I should care of) as for memory : I instance the BMP array invoking ptrBMP = new clsMyStructColor [TotSize]; and I expect the structs are aligned correctly as NEW knows its task. >> disk layout are the very same raw binary. >> I was asking help in making sure this was (not if it was useful or not) > No one can tell you if it is the same without knowing the file format. I just said it : the stupidest format of all 16 bit (width) - 16 bit (height) - N x 32 bit (R,G,B,alpha) where N = width x height = number of "pixels" > There is nothing wrong with having the ram and disk layout the same - oh happy to know ! :) > layout is not directly usable in ram, then it often is /not/ a > convenient and efficient choice - and if it /is/ usable directly in ram, > you don't need or want "pack". I was asking about the specific case > However you look at it, "pack" is usually (but not always) the wrong > choice. You should only consider it once you have eliminated better > alternatives. for a starting, I tried to use a 32 bit total size, hoping it would have been packed regardless of any "hints" (pragma). > As for asking for help here, you are getting the help you need even if > it is not exactly what you asked for. not a problem, every advice is appreciated >> of different layout, in a single read operation ? I can't figure out this > First, you take a step back. You look to see if the packed file really > is "packed", it is, as both Gambas supports BYTE format (And sizeof()) and BYTE-oriented streams. No overspace is generated. Then I have to worry about the C++ back end, to comply with this fact. I think the designer of Gambas relies very strongly upon C libraries and mind-shape, apart from strings (where he had to welcome BASIC users who want strings the basic way). > in the sense of having unaligned data that would have > padding in a normal struct. I have seen no answer to this (unless it is > later in this post), despite asking this /crucial/ question. the files are packed. > If the format is already good, you are done. One memcpy, or read from > the file directly to a suitable buffer, or memmap to the file directly > (no reading or writing needed). memmap is a problem in that I don't know how exactly works and whether or not I'll be able to interoperate with memory files opened in gambas I am also considering to use some memory files supported directly by the OS (here on linux files created on /shm virtual folder are designed for such FAST temporaries to be shared, but with portable stream syntax). Using /shm would imply no specialized load/store code, just the normal file access => delegating the ram usage to the OS. > If the format is bad, the next step is to consider changing the format. just observation. So, the format is wrong ? > If the format is bad, and cannot be fixed, then you have to write reader > and writer functions that unpack and pack the data into the right > formats. Reader and writer functions are common for all sorts of well, I'd be considering these for small size, complex structured input, not for a 4-12 MB size of simple pixels. It would be a blood bathe > header and then allocating memory depending on the size. It is very > normal to have a function that reads in the data format and uses it to > populate an internal format. in fact, minimally, I do this. First create the container, with just a couple of members, then depending on their value, size the buffer and allocate it, then load the file in it. > Perhaps your file format uses 8-bit > unsigned data for colour channels, but your internal format uses > floating point because that suits your processing needs. On certain routines I use floating point, but only temporarily, as I never STORE floating point pixels. I don't need a huge precision, as operations are not supposed to be applied multiple times on the same picture, creating rounding additive errors. > expand it to a raw array. There are all sorts of things that go on in > typical reader functions. Making them a "single operation", whatever > that might mean, sth encoded in a single call to fread / fwrite, at least for the pixel data block. The header is distinct > is rarely relevant - code that uses these functions has > a "single operation" of calling the reader function. well, fread/fwrite may maybe internally operate differently than expected, but in this case I would not be able to do better I guess :) > of course. > (And to be clear - I did not right this to be rude, or insulting, or > demoralising, and I hope it did not come across that way. no problem, really >> I don't know. Just searching a way to do binary read/write in one single >> shot directly to/from RAM without any conversions. > Doing this all "in one single shot" should not be an aim. Doing it in a I wish to both get fast disk I/O but also limit the try/catch trapping. I have the habit to catch or check errno on every disk access. A single huge read/write makes the code thinner than splitting the accesses in many place and having to multiplicate the error condition testing. >> the pillar. > Fair enough. So get it /right/ by designing the right data structure > /now/, rather than picking a bad structure from the start. please give your judgement about the struct I have described before, which drawbacks seems to have or don't have. > Start with a member of that size for convenience - I like a constant > marker to make it easy to tell that you are using the right file type. > (The value here is the string "Picture".) I have stripped everything non necessary as this raw format is only a temporary. When I actually store files, I export them as PNG of JPG or GIF by Gambas code. So my internal format was really minimal. >> personal) format for intermediate raw data. >> It does not seem to be more sophisticated than this. > Then it is inexcusable to have a format that needs "packed". That just oh I completely disagree with this point ! The format has to be packed as the C++ library receives the file from an other source of data that offers them in that form, so it's mandatory. And also the caller expects to get the transformed data back in the same packed form. > means totally pointless complications, inefficiencies, and non-portable > code. nope, I have constraints to fullfil. Maybe inefficient, maybe non portable (who cares ?), but surely not pointless, as otherwise data exchange would not work at all -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato) |
| David Brown <david.brown@hesbynett.no>: Nov 21 01:25PM +0100 On 21/11/2019 03:33, Reinhardt Behm wrote: >> QT has its explicitely sized integers (even if no 8-bit sized) > Of course it has: Q_UINT8 > The standard way would be (u)int8_t, if it is defined in your compiler. And if it is not defined by the compiler, there is no Q_UINT8 type either. In fact, there is no QT for the target. (The exception here would be a very old version of a poor quality compiler that does not support C++11 or C99 - then you might be missing <stdint.h> and <cstdint>.) |
| David Brown <david.brown@hesbynett.no>: Nov 21 01:22PM +0100 On 21/11/2019 01:00, Soviet_Mario wrote: >>> unsigned 8 bits integer type ? >> uint8_t from <stdint.h>, or std::uint8_t from <cstdint>. > i inquired, and they expand to a typedef related to unsigned char That is because <stdint.h> and <cstdint> (and other standard library headers) are adapted to suit the target processor. uint8_t is a bad example here, because (AFAIK) if a compiler supports a type that could be used for uint8_t, then "unsigned char" is always going to be suitable for it. (That does not mean it is the only choice.) Consider uint32_t. This type is guaranteed to be 32-bit, unsigned, with no padding bits. If a C99/C++11 compiler has a type that can fit these requirements (along with a matching int32_t), it /must/ provide uint32_t and int32_t types. But it is up to the implementation - the compiler and the standard headers - to decide how to do that. On one platform, it might have "typedef unsigned int uint32_t;". On another, it could have "typedef unsigned long int uint32_t;". On another, it could have "typedef __UINT32_TYPE__ uint32_t;". The standard headers, like <stdint.h>, are /not/ portable - they are fixed for the given compiler implementation. Thus when you want a 32-bit unsigned integer, you use "uint32_t" and let the C/C++ implementation worry about how it makes that work on this particular target. The fixed size types exist precisely to let you write code in a portable way with specific requirements for the types, without having to know details of the underlying target. > opacity/transparency from images, so I have to get two different pieces > of programs (a front end in gambas and this would-be static library to > speak the same language and have the same data layout). Use uint8_t. > To be very very tight fisted, I could even have devoted a SINGLE BIT to > the transparency mask, but addressing would have become far slower. So I > waste 7 bits ! but no more. uint8_t is always 8 bits. No more, no less. > there (and also align issue did not show up). > the gambas frontend has a native type BYTE (0-255 range) for the > transparency mask so I have to replicate it in the library C and C++ have an equivalent type. It is called "uint8_t". |
| Keith Thompson <kst-u@mib.org>: Nov 21 11:30AM -0800 David Brown <david.brown@hesbynett.no> writes: [...] > uint8_t is always 8 bits. No more, no less. [...] Yes. Expanding on that, uint8_t is always 8 bits *if it exists*. (And in the real world, it almost always exists. You're far more likely to encounter a very old implementation that doesn't support <stdint.h> or <cstdint> than to encounter one that does have those headers but has CHAR_BIT>8.) -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
| David Brown <david.brown@hesbynett.no>: Nov 21 10:54PM +0100 On 21/11/2019 20:30, Keith Thompson wrote: > likely to encounter a very old implementation that doesn't support > <stdint.h> or <cstdint> than to encounter one that does have those > headers but has CHAR_BIT>8.) That is certainly true if by "in the real world" you mean "platforms that support QT" :-) I've worked with a couple of devices that have 16-bit CHAR, and been indirectly connected with a project using one with 32-bit CHAR. These were DSP devices, but are current devices, with new family members being added regularly. But it is very rare that you want much software that will be portable between these sorts of chips and other more "normal" processors. Balancing that, I have a few compilers that I still have occasion to use that don't support <stdint.h> (or C++, for that matter). |
| David Brown <david.brown@hesbynett.no>: Nov 22 10:10AM +0100 On 22/11/2019 09:37, Keith Thompson wrote: > uint8_t elements is guaranteed to be 32 bits, but a struct containing > such an array is not -- but it's a nearly safe assumption that there > will be no padding between the elements or at the end.) While it is true in theory that a struct can have extra padding at the end (beyond what is needed for an array of the struct to have proper alignment for all members), are there any compilers that have done so in practice? Another option is to cover all bases with a union: typedef union { uint32_t combined; uint8_t rgba[4]; struct { uint8_t red, green, blue, alpha; }; } pixel; _Static_assert(sizeof(pixel) == 4, "This only works on real systems!"); (Watch out for endian issues giving different orders within these parts - that's always a concern for portable code when matching external file formats.) |
| Christian Gollwitzer <auriocus@gmx.de>: Nov 22 07:26AM +0100 Am 21.11.19 um 17:20 schrieb Paavo Helde: > than char. For example, long is 32 bits in 64-bit MSVC and 64 bits with > 64-bit gcc on Linux. > However, for your purposes std::uint32_t should work fine. Why not #pragma pack(1) struct pixel { uint8_t red, green, blue, alpha; } ? That would make more sense to me than uint32_t and bit-twiddling to get the channel values. Christian |
| Keith Thompson <kst-u@mib.org>: Nov 22 12:37AM -0800 > Am 21.11.19 um 17:20 schrieb Paavo Helde: [...] > } > ? That would make more sense to me than uint32_t and bit-twiddling to > get the channel values. Because #pragma pack is non-standard? If you only care about implementations that support it as an extension, that's fine, but the OP seemed very concerned about portability. An array of uint8_t could also work: typedef uint8_t pixel[4]; enum { red, green, blue, alpha }; Or an array wrapped in a struct to allow assignment. (An array of 4 uint8_t elements is guaranteed to be 32 bits, but a struct containing such an array is not -- but it's a nearly safe assumption that there will be no padding between the elements or at the end.) -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
| Soviet_Mario <SovietMario@CCCP.MIR>: Nov 22 11:31AM +0100 Il 22/11/19 09:37, David Brown ha scritto: > If you are using "pragma pack" (or gcc "packed" attribute), you are > probably doing something wrong. It can have some uses when dealing with > file formats it is exactly this second case : two programs have to communicate and store picture files in a compact way (and if I'll manage to, even exchange such pictures loaded in memory) upon a single big binary "fread" from disk or save with a single raw "fwrite" to disk. I can't find it acceptable that the DISK layout and RAM layout may differ as to packing aspects. Non only for the waste of space (a large waste as pictures could be some tens megapixels), but as in such case I would have to read/write only single elements at a time. Unacceptable (*). I must be allowed to load and save fast and in a single shot, so 1:1 mapping RAM<=>DISK. This requirement is underogatable, even if I agree with all other remarks you make afterwards ... (*) well actually I do not make strictly a single load/save as stated. First I save/load a very small descriptor with WIDTH/HEIGHT stored as 16 bit integers, then, aware of the array size of the buffer, alloc and fread or fwrite down. It's a very "stupid" non standard format, but I don't need to export this directly. When in gambas I save using its native functions. The C++ engine is just supposed to transform pictures and save in raw format. -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato) |
| David Brown <david.brown@hesbynett.no>: Nov 22 12:38PM +0100 On 22/11/2019 11:23, Öö Tiib wrote: > It usually works in practice but is undefined behavior in C++, so Bjarne > Stroustrup and Herb Sutter suggest against it in C++ Core Guidelines. > http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ru-pun You are right - I was thinking in C terms, where this /is/ defined behaviour. For C++, you'd need to put it all in a class and make appropriate accessor functions. On the plus side, that would let you make an endian-independent solution, and if it is done well the compiler's optimiser will eliminate all overhead. On some compilers, like gcc, the union type-punning is guaranteed to work in C++ too. But then the code is not portable. |
| David Brown <david.brown@hesbynett.no>: Nov 22 03:18PM +0100 On 22/11/2019 13:55, Öö Tiib wrote: > But I did nowhere say that the effect of raised storage efficiency is > guaranteed to be significant or helpful anyhow? I only said that > there usually is that effect. Period. Lack of that effect is less usual. Fair enough. > Careful design and arrangement of data in way that padding is > minimal is effort and so is rarely invested. I would expect anyone who cares about the storage efficiency to put in that effort. > But what you say about > lot of members clearly contradicts with example that I brought in > next sentence. Yes, but see below about that one. > It is third option that will save memory like packing on this example > It is worth to try out as well but unfortunately it is also not a silver > bullet. If programming was full of silver bullet solutions, it would not be nearly as much fun :-) > Those are also available only on some (I agree that common) platforms > and usefulness of those assumes that by "processing" we did mean > (I also agree that those are common) sequential for loops. Of course. It is only a possibility, not something that is always useful. > 64-bit IEEE 754 doubles there is huge supply of NaNs plus two Infs) > so I assumed that the char under question carries more than one bit > of information in it. I was thinking of something roughly like a std::optional<double>, but where you want greater storage efficiency. Of course there are endless use-cases for structures similar to this, and many ways to handle it. I am just showing some ideas that can often be better than throwing "packed" into the mix (while still accepting that /sometimes/ "packed" is the best choice). > answer to your claim that these can lead only to significant > negative effects. Also it is often cheapest alternative to try > and test what the two pragmas added to code cause. It might be that there has been a little mixup about which claims referred to which uses of "packed" (without saying who has mixed things up, as it was likely to be me). In general, I agree that "packed" may have positive effects, negative effects, or no effects, and any effects may be significant or insignificant. I say there are usually, but not always, alternatives that could do better. But I agree that "packed" is often an easy choice from the development viewpoint. However, I would say it is almost always a bad choice to start off with a design that /requires/ "packed" - the OP has no reason at all for doing that. The case where I said there could never be any positive effects, but might be negative effects, was a poster who suggested "packing" a struct consisting of 4 uint8_t members. There, I think we can agree, it could never lead to increased storage or runtime efficiency on any real platform. (There is, I believe, a very hypothetical possibility of the struct having extra padding.) And it is certainly possible that on some platforms with some compilers, there could be negative effects. |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Nov 22 02:11PM -0500 On 11/22/19 1:35 PM, Soviet_Mario wrote: > Il 22/11/19 15:04, David Brown ha scritto: ... > I have abandoned the unsigned Bit_Field : 8 solution as soon > as you (a lot of people) stated that u_int_8 MUST have uint8_t > exactly 8 bits. It must have exactly 8 bits, if it exists. uint8_t is optional. And on any C99+ implementation that fails to support uint8_t, and on any C platform where unsigned char doesn't have 8 bits, you can't do what you want to do anyway. > produce any reasonable effect, neither slowness), either is > NECESSARY (and so the slowing effect is a unavoidable price > that I MUST pay either) Correct - it is both useless and unnecessary - in this context. Don't extrapolate from this case to the general case. It is very specifically the fact that you are trying to pack something that cannot possibly be bigger than a byte, and therefore cannot have an alignment requirement bigger than 1, that renders the pragma useless and unnecessary. > that, but not particularly so in low level (some couple of > tens of years ago I used to stuff C code with inline "asm" > statements or even __emit() calls). You don't appear to understand why the fact that you're trying to use an 8-bit type guarantees that #pragma pack will be useless and unnecessary - so there's some low-level stuff you don't understand yet. > either > 3) it is NOT SUFFICIENT (in this case, luckily unlikely, > nothing would have worked fine at all) On implementations where CHAR_BIT==8, scenario #1 applies. On implementations where CHAR_BIT>8, scenarios #1 and #3 both apply. ... > u_int_32 AllChannels; uint_32 >> padding in a normal struct. I have seen no answer to this (unless it is >> later in this post), despite asking this /crucial/ question. > the files are packed. OK - which fields are positioned differently from the way they would be positioned if not packed? |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Nov 22 10:52AM -0500 On 11/22/19 10:49 AM, James Kuyper wrote: > that implementation. If that alignment requirement is greater than the > requirements of any of the member types, that will sometimes require > padding at the end of the struct. I said that wrong. Unless all members of the struct have the maximum alignment requirement, it's possible that such an implementation would have to put padding at the end. |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Nov 22 10:56AM -0500 On 11/22/19 4:37 AM, Öö Tiib wrote: > On Friday, 22 November 2019 10:37:59 UTC+2, David Brown wrote: ... >> full size, packed means you can get misalignments, which can have a very >> significant impact on efficiency in some situations. > Huh? Packed structs usually lead to raise of storage efficiency. He said efficiency, not "storage efficiency". If there's any difference between the packed and unpacked version of a struct, the packed version usually requires slower access. If that weren't the case, there'd be no motive for the implementation to make the unpacked version different. |
| Manfred <noname@add.invalid>: Nov 22 05:13PM +0100 On 11/22/2019 12:38 PM, David Brown wrote: > appropriate accessor functions. On the plus side, that would let you > make an endian-independent solution, and if it is done well the > compiler's optimiser will eliminate all overhead. It is defined behavior in C++ too, but you have to pay extra care (compared to C) in order to ensure that only the active member is accessed. |
| Jorgen Grahn <grahn+nntp@snipabacken.se>: Nov 22 06:56AM On Fri, 2019-11-22, Öö Tiib wrote: > manufacturer or forum or fan-club of that library. For me (if to try > to be straightly honest) the whole product feels like "dirt" or > "digital waste", sorry. The API looks ugly, but maybe the actual simulation is good? > Usenet group comp.lang.c++ is meant to > discuss standard C++ and so such odd libraries are not topical > here. I think the OP is really asking about basic C++ programming, not so much the library. It's still difficult to come up with a good reply though ... he can wrap the code in void helper() { // the code above } but that will just create and start sixLbrApps and then (I guess) immediately destroy it. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
| 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