Wednesday, July 27, 2022

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

Muttley@dastardlyhq.com: Jul 27 07:52AM

On Tue, 26 Jul 2022 11:59:21 -0700
>>>> >>>lvalue, so `&(struct s){1}` is not valid.
 
>>>> >> Certainly doesn't work with Clang though you'd think if the same
>compiler
 
:
:
 
 
>Most C++ compilers are non-conforming by default, quietly accepting
>extensions that are incompatible with the standard. All conforming C++
>compilers provide a way to issue all required diagnostics.
 
I'm aware of all this. My point is why are some C semantics considered
compilable (albeit with warnings) but the original example of &(struct s){1}
isn't and causes an error even though its perfectly legal in C.
"Öö Tiib" <ootiib@hot.ee>: Jul 27 01:56AM -0700

> I'm aware of all this. My point is why are some C semantics considered
> compilable (albeit with warnings) but the original example of &(struct s){1}
> isn't and causes an error even though its perfectly legal in C.
 
It is because while the compilers implemented extension of supporting
compound literals almost like in C, the result in those extensions is
temporary whose lifetime will last only to end of full-expression. Taking
address of temporary is illegal and so &(struct s){1} is illegal.
 
Why they did not implement the semantics fully like in C is because they
used it like kind of alternative syntax sugar to list-initialization. Since
C++14 however they can not heap-allocate initializer-lists (and did not
do it even before C++14). So the compound literal extension is temporary
for ease of implementation. Some of compilers that do it are open source
so if you want you can perhaps implement more close to C extension
to those.
Muttley@dastardlyhq.com: Jul 27 02:51PM

On Wed, 27 Jul 2022 01:56:23 -0700 (PDT)
 
>It is because while the compilers implemented extension of supporting
>compound literals almost like in C, the result in those extensions is
>temporary whose lifetime will last only to end of full-expression. Taking
 
The expressions lifetime - and hence the temporary shouldn't end until the
function being called returns. It should remain on the stack of the calling
function which is probably what happens in C.
 
>for ease of implementation. Some of compilers that do it are open source
>so if you want you can perhaps implement more close to C extension
>to those.
 
Why? Since they're also already C compilers the code to do it already exists
inside them and is probably a case of setting an internal flag to call it.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jul 27 05:33PM +0100


> Actually "abc" is an array-of-char (or array-of-const-char in the latter
> case). You can discern this by eg. printing what sizeof("12345") is
> (quite a nice quiz question).
 
Yes, I should have added "converts to in most contexts" because that's
usually how the difference gets spotted. To be clear, the string
literal above has type char[4] in C and const char[4] in C++.
 
--
Ben.
Paul N <gw7rib@aol.com>: Jul 27 10:09AM -0700

On Monday, July 25, 2022 at 2:14:50 PM UTC+1, Juha Nieminen wrote:
> syntax that compiles in one but not the other. I'm talking about code that
> does compile as both C and C++, but will be interpreted or behave
> differently depending on which (and this makes them incompatible).
 
As I understand it, the two languages have quite different philosophies. In BCPL there is a stated aim of eliminating hidden overhead. There seems nothing in the history of C to suggest that this aim was dropped, certainly B was developed on a very spartan machine. In contrast the aim in C++ is to try to hide the underlying details.
 
For example, in C, a = b + c is a straight-forward addition, though depending on the types it might be a floating-point addition or it might involve a hidden multiplication by a pointer size. In C++, a = b + c could be anything - for instance, it might concatenate two files to form a third one, involving thousands of disk accesses.
Bo Persson <bo@bo-persson.se>: Jul 27 07:28PM +0200

On 2022-07-27 at 19:09, Paul N wrote:
>> does compile as both C and C++, but will be interpreted or behave
>> differently depending on which (and this makes them incompatible).
 
> As I understand it, the two languages have quite different philosophies. In BCPL there is a stated aim of eliminating hidden overhead. There seems nothing in the history of C to suggest that this aim was dropped, certainly B was developed on a very spartan machine. In contrast the aim in C++ is to try to hide the underlying details.
 
Yes, we call that abstraction. :-)
 
Bjarne uses an onion as his metafor. We don't want to see all the way to
the core all the time.
 
 
> For example, in C, a = b + c is a straight-forward addition, though depending on the types it might be a floating-point addition or it might involve a hidden multiplication by a pointer size. In C++, a = b + c could be anything - for instance, it might concatenate two files to form a third one, involving thousands of disk accesses.
 
I have never understood why this is a problem. In C you can write a =
add(b, c) and it can do anything. How is that easier to see through than
using the + operator?
Jivanmukta <jivanmukta@poczta.onet.pl>: Jul 27 06:32PM +0200

I have object of my class source_file:
 
class source_file {
private:
std::wstring source_file_path;
int current_source_line_no;
bool inside_php, start_inside_php;
int num_source_lines, too_long_line_number;
std::vector<std::string> source_lines;
std::vector<std::pair<int, std::string>> tokenized_lines;
std::vector<std::pair<int, std::string>>::const_iterator
current_tokenized_lines_iter;
size_t max_line_len, too_long_line_len, max_found_line_len;
public:
source_file(size_t max_line_length = 0) { // 0 means 'no limit'
max_line_len = max_line_length;
too_long_line_len = 0;
max_found_line_len = 0;
current_source_line_no = -1;
num_source_lines = 0;
current_tokenized_lines_iter = tokenized_lines.end();
too_long_line_number = 0;
inside_php = start_inside_php = false;
}
size_t get_max_found_line_length() const {
return max_found_line_len;
}
size_t get_too_long_line_length() const {
return too_long_line_len;
}
int get_too_long_line_number() const {
return too_long_line_number;
}
bool open(std::wstring in_file_path);
void close() {
source_lines.clear();
tokenized_lines.clear();
too_long_line_len = 0;
max_found_line_len = 0;
num_source_lines = 0;
current_source_line_no = -1;
}
void rewind() { // go to begin of file
current_source_line_no = -1;
current_tokenized_lines_iter = tokenized_lines.begin();
inside_php = start_inside_php = false;
}
bool get_next_line(std::string &line);
bool change_current_line(std::string line, bool ltrim_line);
void ltrim_current_line();
void get_contents(std::vector<std::string> &contents);
bool change_file_with_contents(const std::vector<std::string>
&contents, unsigned int defines_line_num = 0, unsigned int
defines_num_lines = 0);
void remove_magic_str(); void write(std::wstring out_file_path)
const {
std::ofstream out_file(shortwstr2str(out_file_path));
for (std::string line : source_lines) {
out_file << line << std::endl;
}
}
void tokenize_file(std::string token_name_delim_str);
bool get_next_line_with_tokenized(std::string &line, std::string
&tokenized_line);
};
 
The problem is that in some moment of time source_lines[318] is
unexpectedly modified, I don't know why and when, although the file is
correctly loaded to source_lines[], I mean open() works fine and some
time later get_next_line() returns spoilt string. Conditional
breakpoints don't work (I use VSCodium).
How to find the moment of modification of source_line[318]?
Ralf Fassel <ralfixx@gmx.de>: Jul 27 07:20PM +0200

* Jivanmukta <jivanmukta@poczta.onet.pl>
| The problem is that in some moment of time source_lines[318] is
| unexpectedly modified, --<snip-snip>--
| How to find the moment of modification of source_line[318]?
 
Use valgrind or similar.
 
R'
Bonita Montero <Bonita.Montero@gmail.com>: Jul 27 04:10PM +0200

Am 21.07.2022 um 02:22 schrieb Lynn McGuire:
 
> int5, int int6, int int7, int int8, int int9);
> std::vector <int> tuple (int int1, int int2, int int3, int int4, int
> int5, int int6, int int7, int int8, int int9, int int10);
 
You can have that easier:
 
template<typename To, typename ... Ts>
vector<To> myTuple( Ts &&... params )
requires (convertible_to<Ts, To> && ...)
{
vector<To> vt;
vt.reserve( sizeof ...(Ts) );
auto make_row = [&]<size_t ... Indices>( index_sequence<Indices ...> )
{
((Indices, vt.emplace_back( params )), ...);
};
make_row( make_index_sequence<sizeof ...(Ts)>() );
return vt;
}
 
Works with an arbitrary number of parameters.
Bonita Montero <Bonita.Montero@gmail.com>: Jul 27 04:11PM +0200

Am 27.07.2022 um 16:10 schrieb Bonita Montero:
 
>     make_row( make_index_sequence<sizeof ...(Ts)>() );
>     return vt;
> }
 
Now it's complete, I fogot to forward:
 
template<typename To, typename ... Ts>
vector<To> myTuple( Ts &&... params )
requires (convertible_to<Ts, To> && ...)
{
vector<To> vt;
vt.reserve( sizeof ...(Ts) );
auto make_row = [&]<size_t ... Indices>( index_sequence<Indices ...> )
{
((Indices, vt.emplace_back( forward<Ts>( params ) )), ...);
};
make_row( make_index_sequence<sizeof ...(Ts)>() );
return vt;
}
Bonita Montero <Bonita.Montero@gmail.com>: Jul 27 04:35PM +0200

Am 27.07.2022 um 16:10 schrieb Bonita Montero:
 
>     return vt;
> }
 
> Works with an arbitrary number of parameters.
 
This is even more convenient:
 
template<typename ... Ts>
requires (sizeof ...(Ts) >= 1) && (convertible_to<Ts,
tuple_element_t<0, tuple<Ts ...>>> && ...)
vector<tuple_element_t<0, tuple<Ts ...>>> myTuple( Ts &&... params )
{
vector<tuple_element_t<0, tuple<Ts ...>>> vt;
vt.reserve( sizeof ...(Ts) );
auto make_row = [&]<size_t ... Indices>( index_sequence<Indices ...> )
{
((Indices, vt.emplace_back( forward<Ts>( params ) )), ...);
};
make_row( make_index_sequence<sizeof ...(Ts)>() );
return vt;
}
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jul 27 03:51AM -0700

On Monday, July 25, 2022 at 11:40:50 PM UTC+1, Chris M. Thomasson wrote:
 
> How are you parallelizing a single block?
 
 
I read 384 bytes in from the files, into a big buffer like this:
 
char buf[6][64];
 
Each of the six worker threads accesses the array like this:
 
char (&data)[64] = buf[thread_id];
Encrypt_Data_In_Place(data);
 
So the main thread populates the global array, "buf", sets the workers to work, waits for them all to finish, and then loads another 384 bytes into "buf".
 
You get me?
 
(In a previous post I wrote 8kb with 8 threads but I was just picking nice round numbers. Really I have 6 threads each processing 64 bytes at a time -- yeah I should probably increase that massively).
Paavo Helde <eesnimi@osa.pri.ee>: Jul 27 02:46PM +0300

27.07.2022 13:51 Frederick Virchanza Gotham kirjutas:
 
> So the main thread populates the global array, "buf", sets the workers to work, waits for them all to finish, and then loads another 384 bytes into "buf".
 
> You get me?
 
> (In a previous post I wrote 8kb with 8 threads but I was just picking nice round numbers. Really I have 6 threads each processing 64 bytes at a time -- yeah I should probably increase that massively).
 
If you are doing things like this, you should also turn attention to
cache lines and false sharing. See e.g.
std::hardware_destructive_interference_size
("https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size")
 
64 bytes separation is probably just fine (for the current hardware,
that is).
scott@slp53.sl.home (Scott Lurndal): Jul 27 02:02PM

>("https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size")
 
>64 bytes separation is probably just fine (for the current hardware,
>that is).
 
There is hardware out in the real world with 128-byte cache lines. Primarily
in the DPU arena.
Manfred <noname@add.invalid>: Jul 27 02:08AM +0200

On 7/26/2022 6:00 AM, Malcolm McLean wrote:
> I don't know because it's ages since I've looked at a modern processor in
> much detail, but the real cost could be much higher than the cost of the
> extra instructions.
 
The cost of /conditional/ branching is significant in modern architectures.
However, a virtual function call is not this case: it's a deterministic
indirection that should be correctly followed (it's not really a
prediction since its destination is known in advance) by the processor.
 
As Scott says, one relevant factor is locality.
Another relevant factor, when it comes to optimization, is that the
compiler cannot inline virtual functions (unless the concrete type is
actually known at the point of call).
"Öö Tiib" <ootiib@hot.ee>: Jul 26 07:49PM -0700

On Wednesday, 27 July 2022 at 03:08:33 UTC+3, Manfred wrote:
> Another relevant factor, when it comes to optimization, is that the
> compiler cannot inline virtual functions (unless the concrete type is
> actually known at the point of call).
 
That is the case with boost::base_collection<Base> that keeps the
elements in sub-containers of concrete type. So for example when element
is accessed through local_iterator<Derived> the compiler knows that type is
Derived, despite container is polymorphic.
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jul 27 03:54AM -0700

On Wednesday, July 27, 2022 at 1:08:33 AM UTC+1, Manfred wrote:
 
> Another relevant factor, when it comes to optimization, is that the
> compiler cannot inline virtual functions (unless the concrete type is
> actually known at the point of call).
 
 
If the concrete type is known at the point of call, then there's no overhead.
 
If the concrete type is **not** known at the point of call, for example you're using a pointer to the Base class type, then the virtualness is actually needed, and it has been implemented the best way possible.
 
Actually I'm really convincing myself here that I should just mark every method virtual.
Paavo Helde <eesnimi@osa.pri.ee>: Jul 27 03:00PM +0300

27.07.2022 13:54 Frederick Virchanza Gotham kirjutas:
>> compiler cannot inline virtual functions (unless the concrete type is
>> actually known at the point of call).
 
> If the concrete type is known at the point of call, then there's no overhead.
 
Only if all code is visible to the optimizer, and the code is simple
enough for the optimizer, and the optimizer actually decides to optimize
that away.
 
With this iostreams example, none of that seems to happen. Even clearing
the stringstream buffer with oss.str(""); is taking more time than the
whole Bonita's "manual" branch.
 
 
> If the concrete type is **not** known at the point of call, for example you're using a pointer to the Base class type, then the virtualness is actually needed, and it has been implemented the best way possible.
 
> Actually I'm really convincing myself here that I should just mark every method virtual.
 
That language has another name.
scott@slp53.sl.home (Scott Lurndal): Jul 27 01:57PM

>> much detail, but the real cost could be much higher than the cost of the
>> extra instructions.
 
>The cost of /conditional/ branching is significant in modern architectures.
 
Not generally. Branch history buffers, prediction hardware
and other facilities in the hardware interact with the speculation
hardware to speculate down the likely path.
 
They work pretty well in general, albeit speculation has it's own
shortcomings vis-a-vis security. Performance or security but not
necessarily both.
Andrey Tarasevich <andreytarasevich@hotmail.com>: Jul 26 05:56PM -0700

On 7/26/2022 12:57 AM, Juha Nieminen wrote:
 
> char str[] = "hello";
 
> can that "hello" even be considered a "string literal", or should it
> be classified as something else?
 
Yes, it is a string literal. I.e. formally it is an independent object
with static storage duration, independent and separate from `str` in
your example.
 
> array-of-const-char (of a size needed to store the contents of the
> string literal). So for example the type of "hello" is const char[6].
 
> However, you can't initialize an array with another array.
 
But you _can_ initialize a char array with a string literal. A special
exception is deliberately made for this specific case in C and C++
standards. They explicitly state that you _can_ initialize a char array
with a string literal and explicitly specify the semantics of such
initialization.
 
--
Best regards,
Andrey
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jul 26 07:24PM -0700


> Yes, it is a string literal. I.e. formally it is an independent object
> with static storage duration, independent and separate from `str` in
> your example.
 
It is a string literal, i.e., it is a source code token starting and
ending with a '"' character. The corresponding object with static
storage duration is not a string literal. It doesn't exist until
execution time.
 
[...]
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
Juha Nieminen <nospam@thanks.invalid>: Jul 27 07:40AM

> <url: https://en.cppreference.com/w/cpp/types/decay>,
 
> But if you make a reference `auto&`, then there must be a more exact
> match with the initializer type.
 
Is there a good reason that they added such confusing needless complexity
to the keyword? What's the purpose of such inconsistent behavior?
"Öö Tiib" <ootiib@hot.ee>: Jul 27 01:17AM -0700

On Wednesday, 27 July 2022 at 10:41:17 UTC+3, Juha Nieminen wrote:
> > match with the initializer type.
> Is there a good reason that they added such confusing needless complexity
> to the keyword? What's the purpose of such inconsistent behavior?
 
They reused the rules of template argument deduction. I am not 100% sure
why but most likely it is because of hoped ease to learn and to implement
both when both are same.
 
Template argument is deduced from function call arguments. To function
we can pass an array as argument but it will decay into pointer. We can take
reference to array but then also in template we need to indicate that the
parameter takes reference with that &.
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jul 27 01:56AM -0700

On Tuesday, 26 July 2022 at 20:03:23 UTC+1, Keith Thompson wrote:
 
> The C standard defines a "string" as "a contiguous sequence of
> characters terminated by and including the first null character".
> C has no string *type*, but it certainly does have strings.
 
The C standard uses a lot of words in a special way. Like "function".
"string" is another of those words.
"gdo...@gmail.com" <gdotone@gmail.com>: Jul 26 08:04PM -0700

every language where count begins at zero be fixed.
puppy 0
puppy 1
puppy 2
...
please. this lends itself to off by one all over the place. pointers of yesterday to think of just one. lol, lol, lol
 
i mean 0. lol
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.

Tuesday, July 26, 2022

Digest for comp.programming.threads@googlegroups.com - 1 update in 1 topic

Amine Moulay Ramdane <aminer68@gmail.com>: Jul 25 07:23AM -0700

On Monday, July 25, 2022 at 3:50:47 AM UTC-4, Noel Duffy wrote:
 
> > i am a "respectable" person, and i am not here to post for too long
> about those ideas of mine, it is why i will from now on post just on
> programming here from time to time.
 
I am posting just 2 posts here, since i have just wanted to inform on an
important subject, but i will not post here for a long time, so don't bother about it.
 
Thank you,
Amine Moulay Ramdane.
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.programming.threads+unsubscribe@googlegroups.com.

Monday, July 25, 2022

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

Juha Nieminen <nospam@thanks.invalid>: Jul 25 01:14PM

Some people often object if someone conflates C and C++, as if C++ were
just a pure superset of C, pointing out that they are, in fact, different
languages and, in some aspects, actually incompatible with each other.
 
That got me thinking: What are all the differences between the two
languages, in behavior and meaning, when it comes to their common syntax?
In other words, I'm not here talking about different keywords and different
syntax that compiles in one but not the other. I'm talking about code that
does compile as both C and C++, but will be interpreted or behave
differently depending on which (and this makes them incompatible).
 
Here are some of the things that come to mind. What other things are there?
 
1) A 'const' variable at the global scope will have external linkage by
default in C (unless explicitly made to have internal linkage with
'static'), but internal linkage by default in C++ (unless explicitly made
to have external linkage with 'extern').
 
2) The type of 'A' is int in C, but char in C++.
 
3) This one is really obscure: In C, this:
 
int f(int (*)(), double (*)[3]);
int f(int (*)(char *), double (*)[]);
 
is a valid function declaration, and equivalent to:
 
int f(int (*)(char *), double (*)[3]);
 
(This one is so obscure that I'm certain the vast majority of C programmers,
even experienced ones, would be surprised it even compiles. However, the
example is directly from the C standard, so it's pretty legit.)
 
In C++ the two first lines declare two different functions, taking different
types of parameter. Calling one is not the same thing as calling the other.
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jul 25 04:18PM +0200

On 25 Jul 2022 15:14, Juha Nieminen wrote:
> example is directly from the C standard, so it's pretty legit.)
 
> In C++ the two first lines declare two different functions, taking different
> types of parameter. Calling one is not the same thing as calling the other.
 
Yes, `void` argument list needed to say "no arguments" in C.
 
I guess the most crucial thing is that type punning via union is
well-defined in C, but UB in C++.
 
 
- Alf
Paavo Helde <eesnimi@osa.pri.ee>: Jul 25 06:47PM +0300

25.07.2022 16:14 Juha Nieminen kirjutas:
> syntax that compiles in one but not the other. I'm talking about code that
> does compile as both C and C++, but will be interpreted or behave
> differently depending on which (and this makes them incompatible).
 
This little program outputs 0 when compiled as C, and 1 when compiled as
C++, at least with gcc 10.2. I'm not quite sure if this is meant to be
that way.
 
#include <stdio.h>
#include <stdlib.h>
 
int main() {
 
double x = -0.5;
int y = (int) 2*abs(x);
printf("%d\n", y);
}
"Öö Tiib" <ootiib@hot.ee>: Jul 25 08:51AM -0700

On Monday, 25 July 2022 at 16:14:50 UTC+3, Juha Nieminen wrote:
> example is directly from the C standard, so it's pretty legit.)
 
> In C++ the two first lines declare two different functions, taking different
> types of parameter. Calling one is not the same thing as calling the other.
 
There are not too lot of little things in C that differ from C++ like that:
* C++ has lot of keywords that C does not have or has as macro (bool) or
typedef (wchar_t)
* logical expressions like 1 == 2 result with int (not bool)
* character literals like 'a' are of type int (not char)
* differences with const
* differences with inline
* differences with static
* C has VLAs
* differences in enum type size requirements
 
Those differences can cause same code to compile to different behaviour
in C and C++ silently but it is usually obscure, specially constructed code.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jul 25 05:14PM +0100


> That got me thinking: What are all the differences between the two
> languages, in behavior and meaning, when it comes to their common
> syntax?
 
Let's see...
 
"abc" is of type char * in C and of type const char * in C++.
 
Then there all the keyword differences. For example, in C, new is an
ordinary ID and in C++ restrict is an ordinary ID. There are quite a
few of these!
 
The rules for compatible pointer types are stronger in C++. Basically,
you can only add a top-level const when passing arguments in C.
 
In C++ function declarations, () means (void), but in C it means an
old-style function with unspecified arguments.
 
In C, at file scope, int x[]; is a "tentative definition" (which will
resolve to int x[] = {0}; if there are no further declarations of x) but
in C++ it's just an error.
 
In C, f( (int[]){1} ), calls f with a temporary array (it's a "compound
literal"), but that's forbidden in C++.
 
Some things that are compound literals in C /are/ valid in C++. For
example:
 
struct s { int v; };
...
f((struct s){1});
 
is ok in both, but add a pointer and you get the same difference as
above:
 
g(&(struct s){1}); // ok in C, not ok in C++
 
And now I'm out of time...
 
> int f(int (*)(char *), double (*)[]);
 
> is a valid function declaration, and equivalent to:
 
> int f(int (*)(char *), double (*)[3]);
 
Yes. This is C's rules for "composite types" in action.
 
 
> In C++ the two first lines declare two different functions, taking different
> types of parameter. Calling one is not the same thing as calling the
> other.
 
However, you can, in fact call the second f with a double (*)[] argument
because of C++'s rules about similar types (at least I think those are
the rules that apply here).
 
--
Ben.
Muttley@dastardlyhq.com: Jul 25 04:19PM

On Mon, 25 Jul 2022 17:14:05 +0100
 
>is ok in both, but add a pointer and you get the same difference as
>above:
 
> g(&(struct s){1}); // ok in C, not ok in C++
 
IOW mostly contorted syntax that was probably never intended to be used but
happens to be legal due to the way the C parser works.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 25 05:45PM +0100

On Mon, 25 Jul 2022 13:14:35 -0000 (UTC)
> example is directly from the C standard, so it's pretty legit.)
 
> In C++ the two first lines declare two different functions, taking different
> types of parameter. Calling one is not the same thing as calling the other.
 
One thing I don't think mentioned so far, for those who like
low-level twiddling of trivial types: in C, except for bit-fields all
objects are composed of contiguous sequences of one or more bytes,
which thereby comprise an array of bytes in C. In C++ trivially
copyable or standard layout types (ie C-like types) are required to be
comprised of contiguous bytes, but these do not comprise an "array" of
bytes. Hence you can use pointer arithmetic to access and/or modify the
bytes of object entities in C, and this is a fairly common practice for
some low-level work, but not in C++ (save that in C++, when within a
C-like entity you can at least successively increment a byte pointer by
one because in C++ every object, including a byte, can be treated as an
array of size 1).
 
One other related point is that in C a pointer to any narrow character
type is exempt from the strict aliasing rules, whereas in C++ pointers
to signed char are excluded from the exemption.
Paavo Helde <eesnimi@osa.pri.ee>: Jul 25 07:49PM +0300

25.07.2022 18:47 Paavo Helde kirjutas:
>     int y = (int) 2*abs(x);
>     printf("%d\n", y);
> }
 
This example can be actually made a bit simpler, messing with ints is
actually not needed. I think this is now similar to what I stomped on
myself in real code.
 
#include <stdio.h>
#include <stdlib.h>
 
int main() {
 
double x = -0.5;
double y = 2.0 * abs(x);
printf("%g\n", y);
}
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jul 25 02:48PM +0200

This code parses an unsigned decimal integer spec with possible group
delimiters.
 
Since it's intricate it can probably be very much simplified?
 
Result_uint result = 0;
bool overflowed = false;
char ch; // Declared here to be accessible to the
loop's update expression.
Prev_char previous_ch = '\0';
for( p_end = p_first; p_end != p_beyond; previous_ch = ch, ++p_end ) {
ch = *p_end;
WITH_CONST( ch ) {
if constexpr( group_delimiters_allowed ) {
if( ch == group_delimiter ) {
if( previous_ch == group_delimiter ) {
return Ret( no_result,
Error::consecutive_group_delimiters );
}
continue;
}
}
if( not( ch %in% ascii::digits ) ) { return result; }
const Result_uint before = result;
result = 10*result + (ch - '0');
if( result < before ) { overflowed = true; }
}
}
 
... where `WITH_CONST` just adds `const`-ness to the specified name so
that it's provably not modified in that code block, and where the
`Prev_char` type by default is `char`, but can be dummy (optimized away
operations) when code is instantiated to parse without group delimiters.
 
I declared `ch` before the loop so it can be accessed by the `for` loop
head's update expression, so that that expression can handle the
`continue` statement.
 
I guess if one can get rid of the `continue` then one can move the
declaration of `ch` inside the loop and just say directly that it's `const`?
 
- Alf
Paavo Helde <eesnimi@osa.pri.ee>: Jul 25 04:25PM +0300

25.07.2022 15:48 Alf P. Steinbach kirjutas:
 
> I guess if one can get rid of the `continue` then one can move the
> declaration of `ch` inside the loop and just say directly that it's
> `const`?
 
I see your obscure WITH_CONST macro and counter with my obscure
UPDATE_AND_CONTINUE macro:
 
#define UPDATE_AND_CONTINUE(a,b) {a = b; continue;}
 
std::string_view input {p_first, p_beyond-p_first};
Prev_char previous_ch = '\0';
 
for(const char ch: input) {
if (/*...*/) {
if (/*....*/) {
// ...
UPDATE_AND_CONTINUE(previous_ch, ch);
}
}
// ...
UPDATE_AND_CONTINUE(previous_ch, ch);
}
 
 
Who says my macro is uglier than yours?
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jul 25 04:01PM +0200

On 25 Jul 2022 15:25, Paavo Helde wrote:
>     UPDATE_AND_CONTINUE(previous_ch, ch);
> }
 
> Who says my macro is uglier than yours?
 
Heh :-), it's certainly less reusable functionality, but it's an idea.
 
And I like fresh ideas.
 
Just a shame that C++ doesn't yet formally support push and pop of
macros so that one can freely use local macros...
<url:
https://docs.microsoft.com/en-us/cpp/preprocessor/push-macro?view=msvc-170>
<url: https://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html>
 
I would also have liked language support for `WITH_CONST`. There's the
whole $ space available for new keywords. It could be `$with_const`.
 
Re the `string_view`:
 
that might seem smart but part of the parsing effect is to produce a
final `p_end`, beyond the number spec, where the caller can continue
higher level parsing (if any). That's also the reason for the boolean
`overflow`. To move the `p_end` beyond the spec even if overflow.
 
Thanks,
 
- Alf
Bonita Montero <Bonita.Montero@gmail.com>: Jul 25 12:20PM +0200

I tried to evaluate the performance of ostringstream with MSVC,
clang++-12 under Linux and g++.
 
#include <iostream>
#include <sstream>
#include <vector>
#include <chrono>
#include <iomanip>
#include <array>
 
using namespace std;
using namespace chrono;
 
int main()
{
constexpr size_t N = 1'000'000;
auto bench = []<typename StringGen>( StringGen stringGen ) -> double
requires requires( StringGen stringGen ) { { stringGen( (size_t)123 )
} -> std::same_as<string>; }
{
vector<string> vs;
vs.reserve( N );
auto start = high_resolution_clock::now();
for( size_t i = N; i--; )
vs.emplace_back( stringGen( i ) );
return (double)(int64_t)duration_cast<nanoseconds>(
high_resolution_clock::now() - start ).count() / N;
};
ostringstream oss;
auto genOss = [&]( size_t x ) -> string
{
oss.str( "" );
oss << setw( 8 ) << setfill( '0' ) << hex << x;
return oss.str();
};
cout << bench( genOss ) << endl;
auto genManual = []( size_t x ) -> string
{
using arr_t = array<char, 8>;
using arr_it = typename arr_t::iterator;
array<char, 8> str;
arr_it it = str.end();
while( x && it > str.begin() )
*--it = (x % 10) + '0',
x /= 10;
for( ; it > str.begin(); *--it = '0' );
return string( str.begin(), str.end() );
};
cout << bench( genManual ) << endl;
}
 
The above program takes about 300ns for each ostringstream-generated
string on my TR3990X under Windows with MSVC 2022, but only 17ns for
my own generator; it's nearly the same with clang-cl 13 under Windows.
Unter Ubuntu with g++ 11 on a 13 yr old Phenom it's abotu 110 and 36.
clang++-12 under Linux (different standard libary than under Windows)
takes 125 vs. 43ns on the same computer.
I won't expect that a stream is that fast like my hand-optimized code,
but I think that this could go even faster with ostringstream under
Linux, and Windows for sure.
"Öö Tiib" <ootiib@hot.ee>: Jul 25 03:51AM -0700

On Monday, 25 July 2022 at 13:20:09 UTC+3, Bonita Montero wrote:
> I tried to evaluate the performance of ostringstream with MSVC,
> clang++-12 under Linux and g++.
 
...
 
> oss << setw( 8 ) << setfill( '0' ) << hex << x;
 
...
 
> --it = (x % 10) + '0', x /= 10;
 
...
 
Output of those programs is likely different? One looks hex ... other decimal.
 
A function hard-coded for narrow case compared with widely dynamically
configurable one (with all those setw, setfill and imbue) will likely win forever.
For fairness compare with std::to_chars() that has narrowed down the
spec of configurability to be easier to make efficient.
Wuns Haerst <Wuns.Haerst@wurstfabrik.at>: Jul 25 01:36PM +0200

Am 25.07.2022 um 12:51 schrieb Öö Tiib:
 
>> --it = (x % 10) + '0', x /= 10;
 
> ...
 
> Output of those programs is likely different? One looks hex ... other decimal.
 
OOOOOOOOOOh, you're right, hex would be even faster.
And with decimal I won't get all digits in the 8 characters.
Bonita Montero <Bonita.Montero@gmail.com>: Jul 25 01:42PM +0200

Am 25.07.2022 um 12:51 schrieb Öö Tiib:
> configurable one (with all those setw, setfill and imbue) will likely win forever.
> For fairness compare with std::to_chars() that has narrowed down the
> spec of configurability to be easier to make efficient.
 
It's obvious that this is faster, but I didn't expect
the streams to be so slow.
 
auto genManual = []( size_t x ) -> string
{
using arr_t = array<char, 8>;
using arr_it = typename arr_t::iterator;
array<char, 8> str;
arr_it it = str.end();
static char const digits[16] = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
while( x && it > str.begin() )
*--it = digits[x % 16],
x /= 16;
for( ; it > str.begin(); *--it = '0' );
return string( str.begin(), str.end() );
};
 
 
This is the right function but it isn't faster
although there are no slow /10-divisions.
Paavo Helde <eesnimi@osa.pri.ee>: Jul 25 03:53PM +0300

25.07.2022 13:20 Bonita Montero kirjutas:
> I tried to evaluate the performance of ostringstream with MSVC,
> clang++-12 under Linux and g++.
[...]
> I won't expect that a stream is that fast like my hand-optimized code,
> but I think that this could go even faster with ostringstream under
> Linux, and Windows for sure.
 
We have covered this before. C++ streams are slow because of
 
* lots of flexibility, i.e.
* lots of virtual function calls
* lots of dynamic allocations
* locale support
* perform both formatting and file output
 
By using a stringstream you have avoided the file output part and
potentially also the locale support part (not sure about that, maybe on
Linux?). The virtual calls and memory allocations are still there. In
other words, you are using a trained carpenter with a chisel for
preparing firewood, of course it will be slow.
 
If you are concerned about performance, you should start with
std::to_chars() as others have already commented.
Bonita Montero <Bonita.Montero@gmail.com>: Jul 25 03:12PM +0200

Am 25.07.2022 um 14:53 schrieb Paavo Helde:
>    * lots of dynamic allocations
>    * locale support
> * perform both formatting and file output
 
Except from the virtual functin calls this might hurt, but that's
still a metter of implementation. The formatting-part wouldn't be
much different than I do that.
 
Vir Campestris <vir.campestris@invalid.invalid>: Jul 25 12:11PM +0100

On 19/07/2022 19:50, Jack Lemmon wrote:
 
> Perhaps you should post this to Thunderbird Newsgroup where they might
> tell you what your mistakes. Thunderbird is pretty robust newsreader.
 
I did. I even raised a formal bug, and found other people reporting the
same thing.
 
Sadly the Thunderbird team seem more interested in new features.
 
I might get around to downloading the source and investigating, but
despite having just retired I don't seem to have the time.
 
Andy
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jul 24 04:55PM -0700

On 7/24/2022 1:20 PM, Chris M. Thomasson wrote:
> a single-producer/multi-consumer queue. If you are interested in sheer
> performance, there are several interesting options. Perhaps I can help
> you. Do you care if you get FIFO, or LIFO?
 
Oh. Reading your original thread.
"Öö Tiib" <ootiib@hot.ee>: Jul 25 03:21AM -0700

On Sunday, 24 July 2022 at 23:17:44 UTC+3, Chris M. Thomasson wrote:
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
> Yikes! You really should have a backoff in there. Do you want your
> worker threads to be running full speed with absolutely nothing to do?
 
Yes. Whatever spinlock should be held for rather short time. Here we are
misnaming infinitely busy poll loop (that is terrible anti-pattern) as
"spinlock".
 
The symptoms from OP that "CPU fan getting a bit load and the OS
getting a big laggy" are because one of cores is full busy warming room.
It is visible in whatever activity monitor or task manager of operating
system and anyone half-savvy suggests to kill and uninstall it right away.
Juha Nieminen <nospam@thanks.invalid>: Jul 25 05:47AM

> Don't bother, i have just posted 3 posts and i will stop it and i will
> not post for a long time
 
You have told that lie in the past many times.
Bonita Montero <Bonita.Montero@gmail.com>: Jul 25 09:04AM +0200

Am 25.07.2022 um 00:57 schrieb Amine Moulay Ramdane:
 
You have a bipolar disorder, i.e. you're manic-depressive.
You could get a much better life on medication.
Juha Nieminen <nospam@thanks.invalid>: Jul 25 05:44AM

> - Community that works to be welcoming, inclusive, and friendly
 
Especially "inclusive" is a warning flag, because in modern political
vocabulary it means pretty much the exact opposite.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jul 24 05:04PM -0700

On 7/22/2022 7:28 AM, Frederick Virchanza Gotham wrote:
 
> I have one main thread and eight worker threads.
 
> The main thread is reading in data from a file, and at every 8 kilobytes, it distributes the workload evenly to the eight worker threads, so each worker thread processes 1 kB at a time.
 
> By the time all the worker threads have finished processing their kilobyte, the main thread has prepared another 8 kB workload to distribute.
 
 
It depends on how flexible you want to be. Can worker threads begin to
process an 1kb chunk of data _before_ the main thread is finished
getting the 8kb chunk ready, so to speak?
 
Is the 8kb important, or arbitrary?
 
 
> It is very important that the previous workload has been fully processed before the next workload is dished out.
 
So, the main thread cannot read the next 8kb and prepare it for work
_until_ the previous 8kb has been processed?
 
[...]
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jul 24 05:33PM -0700

On 7/22/2022 7:28 AM, Frederick Virchanza Gotham wrote:
> // same workload. This won't happen if each thread takes
> // milliseconds to execute, and if the thread scheduler takes
> // only microseconds to start another thread going again.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
YIKES! This sounds very fishy.
 
> {
> std::this_thread::sleep_for(std::chrono::milliseconds(1u));
> }
 
^^^^^^^^^^^^^^^^^^^^^^^^
 
Strange.
 
 
 
> sem.acquire();
 
> bitmask_started |= (1u << thread_id);
> assert( 0u == (bitmask_finished & (1u << thread_id)) );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 
 
 
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.

Thursday, July 21, 2022

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

Lynn McGuire <lynnmcguire5@gmail.com>: Jul 20 07:22PM -0500

On 7/20/2022 4:42 PM, Cholo Lennon wrote:
> Cholo Lennon
> Bs.As.
> ARG
 
I use function overloading extensively in my C++ code code. Works
great and it is useful to have the same name with different arguments in
many classes. Here is one of my helper functions, tuple:
 
std::vector <int> tuple ();
std::vector <int> tuple (int int1);
std::vector <int> tuple (int int1, int int2);
std::vector <int> tuple (int int1, int int2, int int3);
std::vector <int> tuple (int int1, int int2, int int3, int int4);
std::vector <int> tuple (int int1, int int2, int int3, int int4, int int5);
std::vector <int> tuple (int int1, int int2, int int3, int int4, int
int5, int int6);
std::vector <int> tuple (int int1, int int2, int int3, int int4, int
int5, int int6, int int7);
std::vector <int> tuple (int int1, int int2, int int3, int int4, int
int5, int int6, int int7, int int8);
std::vector <int> tuple (int int1, int int2, int int3, int int4, int
int5, int int6, int int7, int int8, int int9);
std::vector <int> tuple (int int1, int int2, int int3, int int4, int
int5, int int6, int int7, int int8, int int9, int int10);
 
and so on to int60. I also have tupleString and tupleTuple.
 
I also have the following methods in my DesValue class:
 
virtual void setValue (int aValue);
virtual void setValue (double aValue);
virtual void setValue (char * aValue);
virtual void setValue (std::string &aValue);
virtual void setValue (std::vector <int> aValue);
virtual void setValue (std::vector <double> aValue);
virtual void setValue (std::vector <std::string> aValue);
virtual void setString ( std::string aString );
virtual void setString ( std::vector <std::string> aString );
 
Lynn
Gawr Gura <gawrgura@mail.hololive.com>: Jul 20 10:44PM -0700

On 7/20/22 17:22, Lynn McGuire wrote:
>    virtual void setString ( std::string aString );
>    virtual void setString ( std::vector <std::string> aString );
 
> Lynn
 
Is there a specific reason you've chosen to implement your tuple
function out to 60 elements rather than using a std::vector list
initializer?
Juha Nieminen <nospam@thanks.invalid>: Jul 21 05:45AM

> overloading. One of the explanations of this decision is that "function
> overloading is an anti-pattern", because, among other things, "it leads
> to less readable and understandable code".
 
Any language feature can be misused and "lead to less readable and
understandable code". Heck, *function names* can be very easily used to
write incomprehensible code (and believe me I have experience on that,
having had to read a boatload of code made by other people... code that
uses *extremely* poor function and variable name choices. That alone
makes a lot of code ten times harder to understand than it would have to.)
 
I assume that Rust doesn't have support for generic code, then? Because
function overloading is what makes generic code work.
 
I suppose generic code could still be written without function overloading,
but it would be extraordinarily limited. Heck, the arithmetic and comparison
operators supported by the vast majority of languages are "overloaded
functions" of sort (and are part of what makes generic code work). I assume
Rust has different arithmetic types, and operators like + and - work on
all of them, and you don't have to specify different function names for
different types in order to eg. add them or subtract them.
 
User-defined overloaded functions aren't much different from overloaded
operators. It's a bit artificial to deliberately limit the overloading of
functions when the language already has overloading of operators built in.
 
How do you print things in Rust, if it doesn't support function overloading?
Or does it make an exception for itself, for its own elementary functions?
Paavo Helde <eesnimi@osa.pri.ee>: Jul 21 09:04AM +0300

21.07.2022 00:42 Cholo Lennon kirjutas:
> in several prototypes for a single function is really awful).
 
> What is your opinion about the function overloading as an
> "anti-pattern"? is it?
 
Function overloading is great for simple utility functions where one
immediately understands what it is expected to do, and it basically does
the same thing in all overloads.
 
Function overloading becomes anti-pattern when the overloads do
different things. For example, there are processing stages where a
function processes some parameters, then calls another function with the
same name and partially processed parameters. This may create confusion,
especially if I search the codebase for the function name and it is not
immediately obvious which overload is called where. Better to add
suffixes to the names like "stage1" and "stage2" if one cannot think of
better names.
 
If the functions are not related at all and have the same name just "by
coincidence", then it surprisingly becomes easier because then usually
it is obvious at the call site which overload is used.
 
Yes I know there is an IDE command "go to definition" and sometimes this
is even working. Still, the less confusion, the better.
Juha Nieminen <nospam@thanks.invalid>: Jul 21 07:16AM

> immediately obvious which overload is called where. Better to add
> suffixes to the names like "stage1" and "stage2" if one cannot think of
> better names.
 
I have to deal in the past with production code bases where function
overloading was heavily abused (in more or less a manner of "I'm going
to overload this function name because I can", rather than it making sense),
and it made the code that used those overloaded functions extraordinarily
confusing to read.
 
For example, the code would be full of function calls of the form
"convert(a, b);" and that's it. Not very informative, plus there was like
nine billion overloaded versions of that function for different types of
first and second parameter, doing almost every possible thing under the
sun (eg. converting from an int, unsigned, long, unsigned long, float,
double, etc. to a std::string or to a std::wstring, with the corresponding
overloaded versions doing the conversion in the other direction. And that
was just one set of conversions. There were many more, including conversions
between string encodings. All named "convert()", with different types
and amounts of parameters.)
 
In fact, the very fact that the function name didn't even tell if it
was converting from the first parameter to the second or the other
way around made the code really obfuscated to read.
 
And the thing was, absolutely nowhere in the code was there any advantage
in the function being overloaded. In other words, at no point in the
codebase was there any sort of template or abstracted type that would
have benefited from that 'convert()' function being overloaded.
 
If I were to refactor all that code, I would create unique names for
all those functions, clearly stating the types and the direction of
conversion, like:
 
convert_to_int_from_charp(a, b);
convert_to_int_from_string(a, b);
convert_to_string_from_int(a, b);
 
and so on. If, and only if, the need appears for an overloaded version
of some of those functions, then they can be implemented *in addition*
to those more explicit names (the overloaded versions just calling the
more explicitly named versions), for example like:
 
void convert_to_value_from_string(int, const std::string&);
void convert_to_value_from_string(double, const std::string&);
 
etc. Only in the absolute extreme need would I resort to a completely
overloaded name that encompasses all those conversions. Even then I would
still use a name clearer than just 'convert()', even if it's just
something like 'convert_to_value_from_value()' (to indicate which
parameter is the destination and which is the source.)
 
(And no, I most definitely do not subscribe to the "brevity over clarity"
principle of programming. The more code written by other people I have
to deal with, the less I subscribe to the principle. When I have to read
other people's code, I really get an appreciation for clearly named
functions and variables, which are not only clearly named but also
follow a clear consistent naming pattern and convention, rather than
different patterns and conventions being wildly mixed, even within
the same source file.)
 
That being said (and as I mentioned in my other reply to this thread),
function overloading most definitely has its use, especially in
generic code.
Lynn McGuire <lynnmcguire5@gmail.com>: Jul 21 04:17PM -0500

On 7/21/2022 12:44 AM, Gawr Gura wrote:
 
> Is there a specific reason you've chosen to implement your tuple
> function out to 60 elements rather than using a std::vector list
> initializer?
 
I came to C++ from Smalltalk. Tuple was a standard class and function
and was easy to convert using my handwritten converter.
 
Lynn
Lynn McGuire <lynnmcguire5@gmail.com>: Jul 21 04:22PM -0500

On 7/21/2022 2:16 AM, Juha Nieminen wrote:
 
> That being said (and as I mentioned in my other reply to this thread),
> function overloading most definitely has its use, especially in
> generic code.
 
Another one of my favorites are my asString methods.
 
std::string asString ();
std::string asString (void * val);
std::string asString (int val);
std::string asString (long val);
std::string asString (unsigned int val);
std::string asString (double val);
std::string asString (unsigned long val);
std::string asString (const char *val);
std::string asString (int val, const char * conversion);
std::string asString (long val, const char * conversion);
std::string asString (unsigned int val, const char * conversion);
std::string asString (unsigned long val, const char * conversion);
std::string asString (double val, const char * conversion);
std::string asString (long long val);
 
Lynn
Manfred <noname@add.invalid>: Jul 21 01:29AM +0200

On 7/20/2022 11:49 AM, Juha Nieminen wrote:
 
> (To be fair, a couple of those "better than C++" languages have become
> successful on their own right. They have still failed to replace C++,
> though. Maybe the hundreth time is the charm?)
 
One major problem I see with all those wannabe C++ successor is that C++
has built a foundation that is several decades long, which counts for
reliability and stability of the language (until the committee will
manage to ruin this by keeping on doing what they are doing as of late)
These qualities are very valuable in projects and organizations where
product quality matters.
 
In order to gain a comparable level of recognition, a successor of C++
would have to be building a similar foundation, and die along the way.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 21 01:06AM +0100

On Thu, 21 Jul 2022 01:29:08 +0200
> product quality matters.
 
> In order to gain a comparable level of recognition, a successor of C++
> would have to be building a similar foundation, and die along the way.
 
Indeed, as Keynes said "In the long run we are all dead". No one knows
what language people (if they then exist) will be programming in in 100
years time.
 
I don't know how "official" Carbon is at Google. Despite Google's
forays into things like Go, its codebase is heavily invested in C++.
The thing I take from this is that there is some level of organisation
within that company that is dissatisfied with C++'s evolution. Whether
this is a transient phenomenen, some cry for solace, or something more
long lasting remains to be seen.
David Brown <david.brown@hesbynett.no>: Jul 21 04:01PM +0200

On 21/07/2022 02:06, Chris Vine wrote:
 
> Indeed, as Keynes said "In the long run we are all dead". No one knows
> what language people (if they then exist) will be programming in in 100
> years time.
 
We know some of it. We'll still have C, Cobol, and a bit of Fortran :-)
 
> I don't know how "official" Carbon is at Google. Despite Google's
> forays into things like Go, its codebase is heavily invested in C++.
 
These sorts of things are "bluesky" research for Google. They are
willing to finance them in the hope that they pay off, but they won't
bet the company on them.
 
> within that company that is dissatisfied with C++'s evolution. Whether
> this is a transient phenomenen, some cry for solace, or something more
> long lasting remains to be seen.
 
They are not the first developers to realise that C++ is not perfect!
Muttley@dastardlyhq.com: Jul 21 03:01PM

On Thu, 21 Jul 2022 16:01:54 +0200
>> what language people (if they then exist) will be programming in in 100
>> years time.
 
>We know some of it. We'll still have C, Cobol, and a bit of Fortran :-)
 
It'll depend heavily on how hardware evolves and I suspect the hardware
that exists in 100 years will bear little to no resemblence to what we
have now either in physical construction or logical operation. Perhaps it'll
be quantum, perhaps it'll be something that hasn't even been thought of yet.
 
>> this is a transient phenomenen, some cry for solace, or something more
>> long lasting remains to be seen.
 
>They are not the first developers to realise that C++ is not perfect!
 
https://pmac-agpc.ca/project-management-tree-swing-story
 
Number 12 is how C++ started out, Number 6 is what C++ should be, Number 3 is
what the steering committee have created in the last 10 years.
"gdo...@gmail.com" <gdotone@gmail.com>: Jul 21 08:45AM -0700

great name for a language.
David Brown <david.brown@hesbynett.no>: Jul 21 06:52PM +0200

> that exists in 100 years will bear little to no resemblence to what we
> have now either in physical construction or logical operation. Perhaps it'll
> be quantum, perhaps it'll be something that hasn't even been thought of yet.
 
C, Cobol and Fortran have been around for 50 years or more, and are all
still in serious use. Other languages come and go - and some have come,
but haven't gone yet (like C++). So the best guess we have as to the
languages of the future, is these apparently ever-lasting languages. (I
don't claim they will be the /only/ languages, or even the most popular
ones - just that they'll still be around and in use.)
 
Quantum computers are an expensive excuse to play with cool toys. I
think it is unlikely that they will ever actually be cost-effective for
solving real-world problems (as distinct from completely artificial ones
invented just to suit quantum computers). They /might/ turn out to be
helpful for certain specific optimisation problems. But for "everyday"
computing, they haven't a chance, and never will do.
 
(Feel free to contact me in a hundred years if I turn out to be wrong!)
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jul 21 12:39PM -0700

> that exists in 100 years will bear little to no resemblence to what we
> have now either in physical construction or logical operation. Perhaps it'll
> be quantum, perhaps it'll be something that hasn't even been thought of yet.
[...]
 
Wrt quantum... Check this out, Q#:
 
https://en.wikipedia.org/wiki/Q_Sharp
 
;^)
"gdo...@gmail.com" <gdotone@gmail.com>: Jul 21 12:42PM -0700

> helpful for certain specific optimisation problems. But for "everyday"
> computing, they haven't a chance, and never will do.
 
> (Feel free to contact me in a hundred years if I turn out to be wrong!)
 
it's a date. lol, 2122, July 21.
we will be wearing quantum watches synced to our quantum eye glasses and contact lenses.
😂
we will never forget another face or fact. it will always appear before us. cool right.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jul 21 12:45PM -0700

> we will be wearing quantum watches synced to our quantum eye glasses and contact lenses.
> 😂
> we will never forget another face or fact. it will always appear before us. cool right.
 
LOL! Internet on demand. The mere act of a thought will flood the brain
with search results... ;^)
Michael S <already5chosen@yahoo.com>: Jul 21 01:17PM -0700

On Wednesday, July 20, 2022 at 5:08:24 AM UTC+3, Cholo Lennon wrote:
> Carbon, the latest programming language to be built within Google, was
> unveiled today as an experimental successor to C++...
 
> https://9to5google.com/2022/07/19/carbon-programming-language-google-cpp/
 
Sound like they don't have and don't plan to have BDFL.
Which mean mediocrity at best and irrelevance at worst.
Luckily, with google's weight behind them, worst case is not very likely,
"Fred. Zwarts" <F.Zwarts@KVI.nl>: Jul 21 09:47AM +0200

Op 20.jul..2022 om 14:11 schreef Anthony Capobianco:
 
> The name of the function doesn't describe what it does, it describes the intent of a dev using it.
> You use it when you intend to move something. If you only intend to make it an rvalue reference, then you can cast it.
> The intent is different. The compiler doesn't care what you call it, your coworkers might.
 
That is in general difficult to implement, because it is not the dev
using the function who give it a name, but the dev creating the function
who defines the name. When creating a function it might not be clear in
how many ways it can be used. Sometimes functions are used in unexpected
ways, not foreseen when creating the function. Therefore, when creating
a function, one usually give it a name according to what it does. If it
has a name according to its intended use, it may become very confusing
when it is used for other purposes.
That said, in this case it seems that it is very improbable that
std::move will be used for other purposes than moving.
Juha Nieminen <nospam@thanks.invalid>: Jul 21 09:05AM


> The name of the function doesn't describe what it does, it describes the intent of a dev using it.
> You use it when you intend to move something. If you only intend to make it an rvalue reference, then you can cast it.
> The intent is different. The compiler doesn't care what you call it, your coworkers might.
 
I think that the name 'std::move()' breaks more clarity conventions than
that.
 
'move()', as a verb, would indicate that the function itself does something,
in this case, that it does the moving. It would be completely concordant
with myriads of other such functions, like std::sort() (which itself does
the sorting), std::find() (which itself does the finding), std::copy()
(which itself does the copying) and so on.
 
Particularly that last one is extremely telling: Compare "std::copy()"
to "std::move()". They both sound, by their name, extraordinarily
closely related. It sounds like the former copies stuff from one
place to another (doing it itself), while the latter moves stuff
from one place to another (likewise doing it itself).
 
It would be highly bizarre if "std::copy()" would mean "this doesn't
actually copy anything, it just casts the parameter in such a manner
that it becomes copyable".
 
If the latter thing were needed, certainly it would be named something
clearer, like for example std::make_copyable(), or std::cast_to_copyable()
or something along those lines. Not just std::copy().
 
Likewise it would be highly bizarre if "std::sort()" did no sorting but
instead just somehow cast the parameter into something that can be sorted.
 
std::move() is extraordinarily unique among all standard library functions
in that it breaks this fundamental naming convention. Certainly someone
who knows well what std::copy() does but doesn't know what std::move()
does (but knows about move semantics) would assume that the latter does
the same thing as the former, but moving the elements instead of copying
them.
 
It can't even be a question of "move" being a short name. The standard
library doesn't shy away from using very long names if needed. Take for
example:
 
std::filesystem::recursive_directory_iterator::disable_recursion_pending()
Paavo Helde <eesnimi@osa.pri.ee>: Jul 21 01:12PM +0300

21.07.2022 12:05 Juha Nieminen kirjutas:
 
 
> Likewise it would be highly bizarre if "std::sort()" did no sorting but
> instead just somehow cast the parameter into something that can be sorted.
 
Yes, but e.g. std::unique() does not actually make a vector to contain
unique values. Like std::move(), it is only intended to be used as one
step toward the goal.
 
If moving was done by e.g. static_cast<T&&>(x), then each such code line
would need a comment a la "moving the value". Think of std::move() as a
replacement of this comment.
red floyd <no.spam.here@its.invalid>: Jul 21 01:09PM -0700

On 7/21/2022 2:05 AM, Juha Nieminen wrote:
> library doesn't shy away from using very long names if needed. Take for
> example:
 
> std::filesystem::recursive_directory_iterator::disable_recursion_pending()
 
Probably better would have been std::moveable() instead of std:move.
hester holt <hesterholt12@gmail.com>: Jul 21 12:47PM -0700

This is the PDF eBook version for Pathology of the Hard Dental Tissues By Albert Schuurs
(Download link for cheap price) https://booksca.ca/library/pdf-pathology-of-the-hard-dental-tissues-by-albert-schuurs/
olcott <NoOne@NoWhere.com>: Jul 21 02:11PM -0500

On 7/19/2022 7:27 PM, Ben Bacarisse wrote:
 
>> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
 
> I think I turned it off... I've been fiddling with Gnus/Emacs for
> years.
 
*I addressed your plea*
 
*Can you please begin reviewing my work again on comp.theory?*
*I just got out of the hospital I was very sick*
I will post the full C source-code of the halt decider.
 
Primarily I want it addressed as software engineering.
H(P,P)==0 is correct even if H is not a computable function.
 
Only after it is *fully reviewed* at the software engineering
level (which might be a breakthrough in the field of termination
analysis) then I want it reviewed as a computable function.
 
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Bonita Montero <Bonita.Montero@gmail.com>: Jul 21 12:30PM +0200

#if defined(_WIN32)
#include <Windows.h>
#elif defined(__unix__)
#include <pthread.h>