Thursday, November 28, 2019

Digest for comp.lang.c++@googlegroups.com - 25 updates in 4 topics

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: