Saturday, December 7, 2019

Digest for comp.lang.c++@googlegroups.com - 21 updates in 6 topics

Soviet_Mario <SovietMario@CCCP.MIR>: Dec 07 09:06PM +0100

I fork here because this doubt about template is different
from the enum thread
 
I don't know how to code this situation, so I try to write
broken pseudocode that does not compile, hoping to be able
to explain better than with plain words ....
 
I have this situation
 
 
'tt' will be either double or FixedString (a fast wasty
string class for strings up to a maximum size which inside
has an "embedded" fixed array and an used field for shorter
strings to be copied for the exact extent, they are asciiZ
'\0' terminated for support of std functions)
 
 
template <typename tt> class Table
{
tt Dati [constMaxRighe] [constMaxColonne];
 
template <typename xx> Table <xx> ExtractSubTable \
(int * SelectedRowList, int * SelectedColumnList, \
int numRows, int numCols);
}
 
now assume that ExtractSubTable must exist in 4 specializations
 
from Table <double> to Table <double>
from Table <double> to Table <FixedString>
from Table <FixedString> to Table <double>
from Table <FixedString> to Table <FixedString>
 
assume also I would declare and define the body outside the
class header (it will be big)
 
is it possible to code the function ONCE and not four times ?
Overloaded operators are just defined for every possible
double <=> FixedString combinations, so a single generic
function could (I hope and guess) be coded once.
 
I am confused as how to declare it ....
 
template <typename tt> \
template <typename xx> Table <xx> \
Table <tt> :: ExtractSubTable \
(int * SelectedRowList, int * SelectedColumnList, \
int numRows, int numCols)
{
int TgtRow, TgtCol;
Table <xx> RetVal;
for (int Row = 0; Row < numRows; Row++)
{
tgtRow = SelectedRowList [Row];
for (int Col = 0; Col < numCols; Col++)
{
tgtCol = SelectedColList [Col];
// will operator = be chosen properly ?
RetVal.Dati [Row] [Col] = Dati [tgtRow] [tgtCol];
}
}
}
 
the declarators is tempted completely random, please explain
me the order of nesting, or even if a multiple template (I
believe not) like template <tt, xx> is due
 
and also, how to generate the four specialized
ExtractSubTable functions ?
 
I am confused in nested templates;
tnx
 
 
 
How to produce all four
 
 
 
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Paavo Helde <myfirstname@osa.pri.ee>: Dec 08 12:30AM +0200

On 7.12.2019 22:06, Soviet_Mario wrote:
> strings up to a maximum size which inside has an "embedded" fixed array
> and an used field for shorter strings to be copied for the exact extent,
> they are asciiZ '\0' terminated for support of std functions)
 
So, reinventing std::string. Why?
 
 
> template <typename xx> Table <xx> ExtractSubTable \
> (int * SelectedRowList, int * SelectedColumnList, \
> int numRows, int numCols);
 
What's this obsession with backslashes and line continuation? It's not
needed beyond macro definitions.
 
 
> from Table <double> to Table <FixedString>
> from Table <FixedString> to Table <double>
> from Table <FixedString> to Table <FixedString>
 
So, every FixedString will be convertible to double? What happens if it
is an empty string or "abc"? If it is restricted to be numeric why don't
you hold everything in double?
 
> assume also I would declare and define the body outside the class
> header (it will be big)
 
No, it will not be big, It will be two lines:
 
1. Extract subtable of the same type (one function call)
2. Convert it into the needed type (second function call).
 
This is called modular design. The functions implementing those two
lines might be larger, but the result will be less complex than your
design which attempts to do two things at once.
 
When you have got this working and the customer is not satisfied with
the performance, then you might need to look into ways how to improve
it. Note that it is not given that the your solution to do two things at
once in a function is the best solution.
 
> template <typename xx> Table <xx> \
> Table <tt> :: ExtractSubTable \
> (int * SelectedRowList, int * SelectedColumnList, \
 
Weird backslash obsession again...
"Öö Tiib" <ootiib@hot.ee>: Dec 07 04:43AM -0800

On Friday, 6 December 2019 19:44:14 UTC+2, Taylor wrote:
> > rawly newed pointer to document then said that it is wrong and used
> > the most dork tool std::make_shared! I stopped right there.
 
> You should continue watching. He's just using shared_ptr in his example.
 
Huh? Each shared_ptr usage is dynamic allocation of sole object plus
complicating your data from tree to directed acyclic or may be even
introducing directed cycles into your data. Additionally it is rather
expensive (in both performance and storage usage) smart pointer. It
has usages but rare or else you turn your program into as error prone
and inefficient mess as typical Java or C# programs are.
So video where you are casting it into code without apparently no
thought applied is not worth watching. It proves that you are either
snake oil salesman or noob.
 
> A production implementation would use a small-object optimization. In fact, central to his type erasure scheme is reducing the amount of dynamic allocation.
 
Blah blah blah blah? If something can't be written as document then
it is *never* worth watching as video either. I have already posted link
to document and open source implementation of one way how to reduce
dynamic allocations:
<https://www.boost.org/doc/libs/1_71_0/doc/html/poly_collection.html>
C++ is powerful so there are several other ways and each can be
used and discussed in separation or in combination.
Manfred <noname@add.invalid>: Dec 07 06:17PM +0100

On 12/7/2019 1:43 PM, Öö Tiib wrote:
> complicating your data from tree to directed acyclic or may be even
> introducing directed cycles into your data. Additionally it is rather
> expensive (in both performance and storage usage) smart pointer.
The point about shared_ptr in the video is that the speaker starts
presenting a use of shared_ptr, then he shows how bad it is and replaces
it for a while with unique_ptr. However, in the end he resumes the use
of shared_ptr, but only as pointer to const, as a mean to reduce copies.
So it is less stupid than you posed it.
 
That said, I don't like shared_ptr either.
 
It
> has usages but rare or else you turn your program into as error prone
> and inefficient mess as typical Java or C# programs are.
Totally agree on this.
 
"Öö Tiib" <ootiib@hot.ee>: Dec 07 11:45AM -0800

On Saturday, 7 December 2019 19:17:57 UTC+2, Manfred wrote:
> The point about shared_ptr in the video is that the speaker starts
> presenting a use of shared_ptr, then he shows how bad it is and replaces
> it for a while with unique_ptr.
 
Does not matter. Usage of shared_ptr is often outright defect.
Usage of lot of single object allocations/deallocations is
not defect (but usually weak design).
 
> However, in the end he resumes the use
> of shared_ptr, but only as pointer to const, as a mean to reduce copies.
> So it is less stupid than you posed it.
 
Ok, I agree, not so utterly stupid. Making the shared objects immutable
makes it at least valid to process our now directed acyclic data in
embarrassingly parallel manner. So we at least can burden all the
cores (or even GPUs in our typical target architecture) next to
effortlessly when needed.
 
But the prices of dynamic memory management per object, overhead
from expensive pointer, incapability to realize that equivalent
immutable object that we are creating now is already shared
elsewhere and additional trouble during serialization still remain.
I by default resolve those proactively by having special (smart)
factory and special (smart) pointers but shared_ptr can also be
good enough when used like that.
 
However when data logically really has directed cycles in it (that
happens ultra rarely) then I use likes of Parallel BGL.
<https://www.boost.org/doc/libs/1_71_0/libs/graph_parallel/doc/html/index.html>
At least some hope that someone else is testing it too.
 
> > has usages but rare or else you turn your program into as error prone
> > and inefficient mess as typical Java or C# programs are.
> Totally agree on this.
 
So I'm just bit allergic to it. The unreliable stuff that has
resulted from misuse of shared_ptr IMHO keeps damaging reputation
of C++. Unsure what book taught to put it everywhere ... it should
be burnt.
saturnman2008@gmail.com: Dec 07 01:53AM -0800

在 2019年12月6日星期五 UTC+8上午6:21:05,Soviet_Mario写道:
 
> enum class RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
 
> template <RestrictedValues ttVal> class SizedField
> {
public:
static constexpr int aSize = static_cast<int>(ttVal);
 
> The goal is to have a template depending on a restricted
> well defined, and known at compile time, set of integral values
 
> enum RestrictedValues { A = 1, B = 2, C = 4, D = 8 };
 
 
template <RestrictedValues ttVal> class SizedField
{
private:
unsigned char zzArray [ttVal];
 
 
public:
 
etc etc
 
}
> 1) Resistere, resistere, resistere.
> 2) Se tutti pagano le tasse, le tasse le pagano tutti
> Soviet_Mario - (aka Gatto_Vizzato)
 
 
If my modification fits your requirement?
Soviet_Mario <SovietMario@CCCP.MIR>: Dec 07 06:54PM +0100

Il 06/12/19 23:51, Paavo Helde ha scritto:
> be known at compile time. And vice versa, if something is
> only known only at run-time, you have to do it in an
> old-fashioned run-time way - an if, a switch, etc.
 
yes, in fact the template function which cannot solve one
aspect, has a switch.
But the control variable of the switch must be evaluated by
ITS TYPE (or some internal ID, hash or other info associated
to the type, not its value). In other words it must emulate
sort of a virtual function selector.
 
Many other aspect of the generic container using a lot of
common operators with a homogeneous semantic (assignments,
overloaded by both, comparisons, idem) are instead managed
by the container generically.
 
Indexing like an array but using operator () (row, column)
instead is semantically different for container<double> and
container<fixed_string>, the specialized versions do not
have even the same number of parameters, the latter has a
third parameter for index of character
 
I cannot explain well :\
anyway yes, there are lots of aspects of templates I miss to
understand
 
 
 
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Soviet_Mario <SovietMario@CCCP.MIR>: Dec 07 06:57PM +0100

> static constexpr int aSize = static_cast<int>(ttVal);
>> private:
 
>> unsigned char zzArray [aSize];
 
 
Yes it was a slight of mine to not have converted an enum to
int explicitely.
But the main question was not about that.
Anyway they have just reassured me that the compiler checks
for invalid non-forced cast in the reverse sense (from a
generic integer to the enum) in the specialization of an
instance. That was the source of my concern.
 
The forced manual cast did not worry me, I try not to shoot
in my foot :)
 
 
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
Soviet_Mario - (aka Gatto_Vizzato)
Tim Rentsch <tr.17687@z991.linuxsc.com>: Dec 07 07:53AM -0800

> can't have two libraries that both define `ONESCOMPLEMENT`. Perhaps
> library A defines it as above but library B defines it to produce a
> one's complement.
 
A macro may be defined in places other than public libraries. Or
if it is defined in a public library, and a possible ambiguity is
important to remove, it's easy enough to prefix the macro name
with the namespace used for the library. Would you have the same
objection to using a macro if the macro were not defined in a
public library?
 
> Perhaps both define it as above but using library B you get a
> redefinition warning.
 
I don't know why you think that. Giving several identical
definitions for a macro is allowed in C90, C99, C11, C++98,
C++03, C++11, C++14, and C++17. Testing with gcc, clang, g++,
and clang++ gave no diagnostics even with -Wall and -Wextra.
 
 
> And for example, regarding the so far not mentioned visual
> impact, the shouting uppercase is an annoying eyesore.
 
But that has nothing to do with the macro processor. You are
perfectly free to choose a name that is not all uppercase, or
even all lowercase, if you'd rather. What you said might be an
argument about how to name a macro but it is not an argument
about whether to use a macro.
 
Taking all of these together, the objections given sound more
like rationalizations trying to justify an overarching dislike of
macros than objectively reasoned conclusions.
"Öö Tiib" <ootiib@hot.ee>: Dec 07 08:22AM -0800

On Saturday, 7 December 2019 17:53:56 UTC+2, Tim Rentsch wrote:
> with the namespace used for the library. Would you have the same
> objection to using a macro if the macro were not defined in a
> public library?
 
The authors of libraries are often competitors and so do not like
that you pick and integrate best of breed from their products.
The bigger ones seemingly even enjoy introducing such conflicts
and contradictions. Sometimes even with standard library. Anyone
targeting Windows had sooner or later to look up what to do with
min and max macros in windows.h.
 
> definitions for a macro is allowed in C90, C99, C11, C++98,
> C++03, C++11, C++14, and C++17. Testing with gcc, clang, g++,
> and clang++ gave no diagnostics even with -Wall and -Wextra.
 
Libraries next to never define macro identical to letter and so
tests show opposite:
<http://coliru.stacked-crooked.com/a/65fc657ef88c80fa>
What you suggest to do with these annoying warnings? Silence?
Branch library code? Get the authors to cooperate?
 
> even all lowercase, if you'd rather. What you said might be an
> argument about how to name a macro but it is not an argument
> about whether to use a macro.
 
I agree. We can just configure our tools and text editors to show
macros with different color if we for some reason want these to stand
out visually at all. However lot of coding standards have those rules
in and so majority of macros that we face are in SCREAMING_CAPS.
 
> Taking all of these together, the objections given sound more
> like rationalizations trying to justify an overarching dislike of
> macros than objectively reasoned conclusions.
 
Sure, if you dismiss all problems (that we have tired of facing in
practice) with claim that those do not exist then answering to your
question why we avoid macros is impossible.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Dec 07 03:55AM

Vir Campestris <vir.campestris@invalid.invalid> writes:
<cut>
>>>> <cut>
>>>>> The one that really strained C was the one where incrementing a
>>>>> pointer by 1 went to the next bit. Not byte or word. (TI GPU)
<cut>
> BTW the Dec10 - the 36 bit one I used - an int was 36 bits, but a
> character string was stored as set of 5 7-bit ASCII characters plus
> one pad bit in each word... Never used C on it though.
 
It would be very expensive to implement C using that packed format for
character strings. Some C implementations on other word addressed
machines decided to make char one word; on others arithmetic was needed
to convert between word and "char" pointers. It's notable that,
programmer assumptions aside, word addressed machines are probably more
awkward for C the bit-addressed ones.
 
--
Ben.
James Kuyper <jameskuyper@alumni.caltech.edu>: Dec 06 11:38PM -0500

On 12/6/19 10:55 PM, Ben Bacarisse wrote:
> Vir Campestris <vir.campestris@invalid.invalid> writes:
...
> to convert between word and "char" pointers. It's notable that,
> programmer assumptions aside, word addressed machines are probably more
> awkward for C the bit-addressed ones.
 
I can't vouch for this from personal experience, but I remember being
informed by others in this newsgroup that the byte size was configurable
on that machine. 5 7-bit bytes was just one option. 4 9-bit bytes was
another, and somewhat less expensive than using an entire word to store
a character.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Dec 06 10:20PM -0800

> bit. Other values are available :( [...]
 
> The one with 36 bits (DECSystem10) an address was the address of a
> word, and you couldn't point to a character inside the word.
 
The PDP-10 did have a format, and instructions that used that
format, to access any contiguous set of bits within a 36-bit
word. They were called, IIRC, byte pointers, and would serve
perfectly well as a representation for 'char *' and 'void *'.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Dec 06 10:36PM -0800

> to convert between word and "char" pointers. It's notable that,
> programmer assumptions aside, word addressed machines are probably more
> awkward for C the bit-addressed ones.
 
The PDP-10 had a special representation for pointing to, and
accessing, "bytes" within a word, and instructions for doing loads,
stores, and pointer arithmetic in terms of "bytes" rather than
words. A nice thing about the PDP-10 byte pointers is the width in
bits of a "byte" is part of the stored representation in each byte
pointer. A C implementation on a PDP-10 could choose 9-bit bytes
for 'char' without too much trouble[*]. Alternatively, for a bit of
fun, bytes could be 12 bits, with two bytes for int's, and three
bytes for long (no longer works for C11, naturally), and two 36-bit
words for long long. But 9-bit bytes would work just fine, even for
C11. (Sorry folks - no uint32_t in those implementations.)
 
[*] IIRC, "bytes" in the PDP-10 were treated as unsigned, so
signed types would need sign extension on loading.
boltar@nowhere.co.uk: Dec 07 11:57AM

On Fri, 6 Dec 2019 17:50:39 +0000
>type in calculations?
 
>If you need to use a format code (I don't know how much that is still
>prevalent in C++), is it %d, %ld or %lld?
 
I still use printf, cout is bloody awful for simple text formatting. I've
seen multiple lines of setfill, setwidth etc loads of times, all of which could
have been done with something like a 20 char printf format.
 
But yes, officially you need to know the size of what you're passing to printf
(and scanf) so it outputs correctly, though given both are built into the
compiler I imagine the compiler could be a bit smart about it and promote/demote
as appropriate but I don't know how often thats done, if ever.
 
>> Sorted.
 
>You use a library where the author also 'sorted' by using a type 'mylong'.
 
stdint.h is an official standard header file and has been for decades.
Bart <bc@freeuk.com>: Dec 07 12:04PM


>>> Sorted.
 
>> You use a library where the author also 'sorted' by using a type 'mylong'.
 
> stdint.h is an official standard header file and has been for decades.
 
Sorry, I thought from the names used in your examples that you were
typedef-ing myint and mylong, rather than declaring instances with those
names.
 
In that case, you don't know whether your typedef-ed 'mylong' is going
to be defined on top of the same ?intN_t types as someone else's 'mylong'.
boltar@nowhere.co.uk: Dec 07 01:05PM

On Sat, 7 Dec 2019 12:04:15 +0000
>names.
 
>In that case, you don't know whether your typedef-ed 'mylong' is going
>to be defined on top of the same ?intN_t types as someone else's 'mylong'.
 
Eh?
 
If you want to be sure of the size of an int or long just use the official
typedefs for 32 and 64 bit types. I don't see what the problem is.
Bart <bc@freeuk.com>: Dec 07 01:16PM


> Eh?
 
> If you want to be sure of the size of an int or long just use the official
> typedefs for 32 and 64 bit types. I don't see what the problem is.
 
Yeah, /I/ can do that. The problem is not everyone else will do so.
 
Is int64_t* the same as long*? Sometimes yes, sometimes no, sometimes it
depends. Is a 1234L constant equivalent to int64_t, or int32_t?
 
Messy, but I was originally replying to this comment:
 
[PH:] "As a result, now they [MS] cannot change 'long' to 64-bit because
they have abused it so much."
 
As I said, at least on Windows, you know it will be 32-bits.
"Öö Tiib" <ootiib@hot.ee>: Dec 07 05:49AM -0800

On Saturday, 7 December 2019 15:16:38 UTC+2, Bart wrote:
 
> > If you want to be sure of the size of an int or long just use the official
> > typedefs for 32 and 64 bit types. I don't see what the problem is.
 
> Yeah, /I/ can do that. The problem is not everyone else will do so.
 
That is the problem of those others who do not use official typedefs.
Why it is problem of yours?
 
> Is int64_t* the same as long*? Sometimes yes, sometimes no, sometimes it
> depends.
 
If it somehow matters use std::is_same_v<int64_t*,long*>, it is compile
time bool. But I don't use long* in my code anywhere so it does not matter.
 
> Is a 1234L constant equivalent to int64_t, or int32_t?
 
Same there. I don't use any longs in code and I don't use L suffixes to
integer literals. As result it is problem of those others who do it
wrong.

 
> [PH:] "As a result, now they [MS] cannot change 'long' to 64-bit because
> they have abused it so much."
 
> As I said, at least on Windows, you know it will be 32-bits.
 
Where Windows API has long in interface? Signed 32 bit integers seem
everywhere to be LONG or INT32 in it. So user can use conversions
to those (often nop conversions) where integrating with Windows API.
Everywhere else it does not matter.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Dec 06 10:12PM -0800


> "Microsoft Exploring Rust as the Solution for Safe Software"
> https://www.infoq.com/news/2019/11/microsoft-exploring-rust-safety/
 
> I doubt it.
 
Repeating a similar comment made in another posting, I propose
a rule of thumb for postings like this one: unless a posting is
likely to generate a substantial fraction of responses that are
simultaneously of interest in both comp.lang.c and comp.lang.c++,
it should be multi-posted rather than cross-posted (specifically
for c.l.c and c.l.c++).
Bonita Montero <Bonita.Montero@gmail.com>: Dec 07 07:28AM +0100

> simultaneously of interest in both comp.lang.c and comp.lang.c++,
> it should be multi-posted rather than cross-posted (specifically
> for c.l.c and c.l.c++).
 
The article is related to C as well as C++-programmers.
Multiposting is therefore stupid here.
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: