Monday, July 15, 2019

Digest for comp.lang.c++@googlegroups.com - 18 updates in 7 topics

Soviet_Mario <SovietMario@CCCP.MIR>: Jul 16 12:00AM +0200

I've been a long time far from C++ and I realize I have
forgotten most, and moreover don't understand "modern" C++
.... anyway
 
When in a function (member or not is irrelevant) I build an
aggregate object (class / struct, possibly nested with
other), and this aggregate has a DEFAULT public constructor
which does not resort to new or new [], but then the said
former function invokes some class methods that DO some
dynamic allocation, and then the function returns passing
outside a copy by-value of the built object to the caller,
placed "partially" on the stack, the final copy will be
shallow or deep ?
With shallow I mean : every automatic member not requiring
new or new [], with deep copy I mean exact copy (or even the
temporary itself ...).
 
another maybe relevant detail
is it relevant whether the COPY constructor is defined or
the default one ? How behaves a default generated copy
constructor ? Does it perform also new/ new [] operations ?
 
Is it really the COPY constructor that is called on such a
situation (returning a complex type by-value instead of
by-pointer) ?
 
or a COPY constructor is given, which does not do deep copy,
but just "automatic" data is replicated.
 
 
In case I defined a COPY constructor making dynamic
allocation, is it : 1) required, 2) optional or 3)
deprecated and possibly dangerous define also an explicit
DESTRUCTOR making cleanups ?
 
TY
 
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
"Öö Tiib" <ootiib@hot.ee>: Jul 15 03:40PM -0700

On Tuesday, 16 July 2019 01:01:03 UTC+3, Soviet_Mario wrote:
> outside a copy by-value of the built object to the caller,
> placed "partially" on the stack, the final copy will be
> shallow or deep ?
 
Long sentence that sounded too controversial to
understand. 1) An aggregate can't have ANY user-declared
constructors or destructors. 2) Returning objects of class
type results with RVO (no copies made). 3) Your concept
of shallow copies is also hard to understand:
 
> With shallow I mean : every automatic member not requiring
> new or new [], with deep copy I mean exact copy (or even the
> temporary itself ...).
 
What are automatic members? Snipping the rest since it
discusses more of making constructors to aggregate.
Soviet_Mario <SovietMario@CCCP.MIR>: Jul 16 01:18AM +0200

On 16/07/19 00:40, Öö Tiib wrote:
>> placed "partially" on the stack, the final copy will be
>> shallow or deep ?
 
> Long sentence that sounded too controversial to
 
sorry for my tangled english :\
 
> understand. 1) An aggregate can't have ANY user-declared
 
I realize now I have mis-used this word (that had a precise
meaning in C++!). So let replace it with "class/struct type
object"
 
> constructors or destructors. 2) Returning objects of class
> type results with RVO (no copies made).
 
could you explain this acronym ?
 
> 3) Your concept
> of shallow copies is also hard to understand:
 
only automatic (on stack) members, no "remote" (dynamic)
data allocated with new / new []
 
>> new or new [], with deep copy I mean exact copy (or even the
>> temporary itself ...).
 
> What are automatic members?
 
the ones completely contained in the object itself.
I took the term automatic from "automatic" variables (with
local scope, built on the stack) contrasted with "dynamic"
variables (allocated manually from the heap and whose
lifetime is to be manually managed too).
 
 
> Snipping the rest since it
> discusses more of making constructors to aggregate.
 
you are right, I mis-used the term !
I just meant some object containing both some automatic
members and also some dynamically allocated ones.
TY
 
 
 
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
James Kuyper <jameskuyper@alumni.caltech.edu>: Jul 12 06:55PM -0400

On 7/12/19 6:12 PM, G G wrote:
 
> along with, int* aPointer;
 
> my question is why associate the *, or & the the type instead of the
> name? i do understand it is a preference.
 
A simple declaration consists of a decl-specifier-seq followed by an
init-declarator-list (10.1p1). In this case, int is the
decl-specifier-seq (10.1.7.2p1) and *aPointer or &numberRef are the only
declarators in their respective init-declarator-lists (11.1p4). That
distinction doesn't matter if the init-declarator-list only contains one
declarator. However, if it contains two or more declarators, I consider
it helpful to keep track of the fact that & and * only apply to the
immediately following declarators, and not to any of the other
declarators in the same list. I find it easier to do so if I keep a
space between the decl-specifier-seq and the init-declarator-list, and
if I don't insert a space between the * or & and the rest of the
declartor that it is part of:
 
int *aPointer, &numberRef;
 
* applies only to aPointer, and & applies only to numberRef. If I wrote
something like
 
int* aPointer, aFunc(void);
 
a newbie might easily make the mistake of thinking that aFunc() returns
an int*, rather than an int.
 
It's a minor advantage, and many people prefer not to declare more than
one declator per declaration, so for them it's no advantage at all.
Juha Nieminen <nospam@thanks.invalid>: Jul 15 08:33PM

> my question is why associate the *, or & the the type instead of the
> name? i do understand it is a preference.
 
For some reason that I do not know (and possibly nobody does),
when C was originally devised (although it might have come from a
precursor language like B or BCPL, I don't know) they decided that
the indicator for a pointer variable, ie. the asterisk, would be
tied to the variable name rather than the type. In other words,
the asterisk is not, in fact, part of the type at all, but a sort
of indicator that "this variable is a pointer".
 
This distinction can be seen, as some have pointed out, when declaring
more than one variable in the same expression:
 
int *x, *y, z;
 
Here x and y are pointers, while z is not. The asterisk, the indicator
that means "this is a pointer", is tied to the variable name, not the
type.
 
Of course this can become a bit confusing when types are used in
contexts other than variable declarations. While C-style typedefs
kind of still follow this principle (as typedef syntax is essentially
just normal variable declaration syntax with just the 'typedef' keyword
added at the very beginning):
 
typedef int *IntPtr;
 
it depends on your point of view whether this is now confusing or not:
 
IntPtr ptr;
 
because now the "this is a pointer" part is part of the type alias,
rather than tied to the variable name.
 
When a function returns a pointer, it also can become a bit confusing,
if you follow that same convention:
 
int *function();
 
The "this is a pointer" asterisk kind of is part of the return type,
kind of isn't. It's a bit confusing. No wonder many prefer writing
it like this for clarity:
 
int* function();
 
which of course means the exact same thing, but is visually clearer.
 
And yes, this is valid C (and C++):
 
int *function1(), *function2(), function3();
 
even though it's quite rarely used. (I bet most C/C++ programmers
weren't aware of that.)
 
C++ makes this even more complicated because there are many more
situations where types are used on their own, without any sort of
variable (or function) name, such as:
 
std::vector<int*> vec;
 
Also here the asterisk kind of is part of the type, kind of isn't.
It's all confusing.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jul 15 11:03PM +0100

> precursor language like B or BCPL, I don't know) they decided that
> the indicator for a pointer variable, ie. the asterisk, would be
> tied to the variable name rather than the type.
 
Neither B nor BCPL had types. C was originally "B with types".
 
 
> int *function();
 
> The "this is a pointer" asterisk kind of is part of the return type,
> kind of isn't. It's a bit confusing.
 
The general idea (now rather battered by history and changes to the
language) is that declarations mirror use.
 
function
 
is a function designator. To call it, you mirror the declaration:
 
function()
 
The result is a pointer. To dereference that pointer you again mirror
the declaration and use *:
 
*function()
 
to get an int.
 
This idea of having declarations mirror use, gave rise to declarations
that have two parts: the base type (like int, double and so on) and what
C calls a declarator where operators like *, () and [] decorate the name
with the same priority as they appear in expressions.
 
Knowing both the history and syntax of declarations, I can't stand
seeing
 
int* function();
 
but I know I am on the wrong side of history here, at least as far as
C++ is concerned. I'm not going to defend it, but you wondered where
it came from.
 
> it like this for clarity:
 
> int* function();
 
> which of course means the exact same thing, but is visually clearer.
 
This is the form that used to confuse me. Not that I didn't understand
it, but I'd worry the author may not know how types work in C++. Now
that is it almost de rigeur to write it this way, there's no reason to
worry -- the programmer is simply following standard advice -- it just
looks odd to me, like writing
 
- a+b
 
where the spacing does not reflect the syntax.
 
 
> int *function1(), *function2(), function3();
 
> even though it's quite rarely used. (I bet most C/C++ programmers
> weren't aware of that.)
 
Don't people learn the syntax of the languages they use anymore? (I'm
joking, of course they don't, but C and C++ were designed in era when
they did.)
 
 
--
Ben.
Lynn McGuire <lynnmcguire5@gmail.com>: Jul 15 03:13PM -0500

"Draft FAQ: Why does the C++ standard ship every three years?" by Herb
Sutter

https://herbsutter.com/2019/07/13/draft-faq-why-does-the-c-standard-ship-every-three-years/
 
Interesting. And the embodiment of tough love, stay on schedule no
matter what.
 
Lynn
Christian Gollwitzer <auriocus@gmx.de>: Jul 15 07:41AM +0200

Am 14.07.19 um 11:16 schrieb Heinz Müller:
> Your code is wonderful! Everyone should code like that!
 
ROFL
G G <gdotone@gmail.com>: Jul 15 06:22AM -0700

On Saturday, July 6, 2019 at 11:54:28 AM UTC-4, Szyk Cech wrote:
> best regards,
> and thanks in advance
> Szyk Cech
 
 
-----------------------------
 
 
template < typename tContainer, typename tString >
tString gJoin( const tContainer &aStringList, const tString &aDelimiter )
{
tString lResult;

for(tString lPart : aStringList)
{
if(lResult.size() > 0)
lResult += aDelimiter;

lResult += lPart;
}

return lResult;
}
Frederick Gotham <cauldwell.thomas@gmail.com>: Jul 15 02:10AM -0700

On Thursday, July 11, 2019 at 3:52:46 PM UTC+1, Öö Tiib wrote:
 
> Your Parameter seems to be proxy to nothing. I don't see how it
> can be useful even in unit test. OTOH big part of C++ code out there
> is useless so it is not sacrilegious to write some more.
 
 
I'm part of a team that writes the firmware for an embedded device.
 
I was told that the firmware used a 3rd party library that has been updated from Version 1 to Version 2. Version 2 is very different, it has a different API. Different functions, different structs, different enums.
 
After changing the Makefile for my own project code to accomodate version 2 of the 3rd party library, I got a load of compiler and linker errors.
 
I needed to get the entire project to compile, so I made a header file called "fake_stuff.hpp" to accommodate the differences in the new version of the 3rd party library. I had to make that "Param" class to get everything to compile.
"Öö Tiib" <ootiib@hot.ee>: Jul 15 03:32AM -0700

On Monday, 15 July 2019 12:10:30 UTC+3, Frederick Gotham wrote:
 
> I was told that the firmware used a 3rd party library that has been updated from Version 1 to Version 2. Version 2 is very different, it has a different API. Different functions, different structs, different enums.
 
> After changing the Makefile for my own project code to accomodate version 2 of the 3rd party library, I got a load of compiler and linker errors.
 
> I needed to get the entire project to compile, so I made a header file called "fake_stuff.hpp" to accommodate the differences in the new version of the 3rd party library. I had to make that "Param" class to get everything to compile.
 
I'm still confused about the whole scenario.
I imagine template (like X) in the new interface of 3rd party library.
That X expects template class argument (like X<T>).
Implementation of that X expects result of address of
operator applied to const instance of T to be default-convertible
into pointer to mutable void and to unsigned? And then you wrote
the Parameter to satisfy concept of that T.
That sounds hard to believe so perhaps I am not understanding the
whole story.
Frederick Gotham <cauldwell.thomas@gmail.com>: Jul 15 04:19AM -0700

On Monday, July 15, 2019 at 11:33:07 AM UTC+1, Öö Tiib wrote:
 
> the Parameter to satisfy concept of that T.
> That sounds hard to believe so perhaps I am not understanding the
> whole story.
 
 
 
Wanna see the compiler errors I get without my crazy class?
James Kuyper <jameskuyper@alumni.caltech.edu>: Jul 15 05:59AM -0700

On Monday, July 15, 2019 at 7:19:24 AM UTC-4, Frederick Gotham wrote:
> > That sounds hard to believe so perhaps I am not understanding the
> > whole story.
 
> Wanna see the compiler errors I get without my crazy class?
 
Yes, along with the code that triggered those errors and, for every class relevant to those error messages, enough of the definition to understand what those messages mean. Note: if you weren't sure what those messages meant, be VERY cautious about dropping something just because you think it's not relevant.
red floyd <dont.bother@its.invalid>: Jul 12 10:44AM -0700

On 7/12/2019 7:17 AM, Scott Lurndal wrote:
> register could contain data or an address.
 
> For that matter, modern x86_64 is actually no so bad (the biggest
> warts with the original 8086/80286 were related to segmented memory).
 
Z8000, anyone? Similar to 68K, but the registers were all general,
no differentiation. Z8000 was 16 bit registers, but could be subdivided
into upper/lower half for bytes, and combined with an adjacent register
for 32-bit registers (e.g. RR0 was R0 and R1 combined).
 
Z80000 was the 32-bit version, doubled the number of registers, and
allowed 64-bit "quad" registers.
scott@slp53.sl.home (Scott Lurndal): Jul 12 08:00PM

>number of bytes in an instruction pipeline are holding rex, data,
>address, escape and other prefix bytes that would otherwise be more
>compactly contained within the instruction.
 
I can't speak for x86, but the AArch instruction encoding is baroque
specifically to make the hardware design easier.
 
Given the microcoded nature of the x86 processor and given that the
majority of frequently used instructions have a single-cycle
latency, I don't see that the complexity of the instruction set has
impacted performance. It does, to a certain extent, impact the area
required, but the vast majority of area on a processor chip is devoted
to L1 and L2 caches.
scott@slp53.sl.home (Scott Lurndal): Jul 12 06:35PM


>(actually, make that three, for those of us who write processor
>simulators for a living, we need to decode (and execute) the instruction
>set).
 
Ah, make that four - our hypervisor did have to simulate a handful
of instructions when trapping guest accesses to virtual PCI I/O devices.
 
e.g.
// Decode the instruction.
c_instr_iterator iter((void *)instr, rip);
 
len = get_operand_length(&iter);
 
// Interpret the instruction.
switch (iter.get_opcode()) {
 
case 0xb60f: // movzb mem, reg
value = trace->mem_read(addr, BYTE);
value >>= ((addr & 0x3) * BITS_PER_BYTE);
value &= (1UL << 8 * BYTE) - 1;
set_reg_value(regs, iter.get_modRM(REG), value, len);
break;
 
case 0xb70f: // movzw mem, reg
value = trace->mem_read(addr, WORD);
value >>= ((addr & 0x3) * BITS_PER_BYTE);
value &= (1UL << 8 * WORD) - 1;
set_reg_value(regs, iter.get_modRM(REG), value, len);
break;
 
...etc for most other instructions that access memory.
 
But it is still very rare for anyone else to care about the
instruction encoding.
David Brown <david.brown@hesbynett.no>: Jul 12 05:21PM +0200

On 12/07/2019 16:17, Scott Lurndal wrote:
 
> Personally, I find the PDP-11 to be a nice design. 68000 had
> differentiated registers (A0-A6, D0-D7) while on the PDP-11 any
> register could contain data or an address.
 
I haven't used the PDP-11, but I have used the msp430 microcontrollers
which have a very similar ISA. And they too are very pleasant cpus to
work with in assembly language or C.
 
 
> For that matter, modern x86_64 is actually no so bad (the biggest
> warts with the original 8086/80286 were related to segmented memory).
 
Certainly it seems to be a lot better than older x86 - more registers
and fewer register specific instructions helps.
Szyk Cech <szykcech@spoko.pl>: Jul 12 05:35PM +0200

W dniu 11.07.2019 o 07:16, Öö Tiib pisze:
> So you want to use module of Qt for writing QML applications but
> you don't want to write QML applications? Nonsense.
 
Programmer can't be so lame to tell this! You talk nonsense!
Qt Quick classes were written in C++ and exposed to QML exclusively. So
there is no technical reasons to not use it in pure C++ apps. Only the
Qt vendor lock politics prohibit programmers from this!
 
If you don't know about Qt history, architecture, and politics - don't
write. Otherwise you appear as ignorant (which is soft term mean: stupid).
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: