Sunday, November 20, 2022

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

Tim Rentsch <tr.17687@z991.linuxsc.com>: Nov 20 05:54AM -0800


> [...]
 
> I don't see how it's so obvious that 'union' was designed from the
> get-go with the intent of using it for type punning.
 
I didn't say anything about how the union construct was designed.
What I did say was that it was expected that unions would be used
for type punning, and that expectation was evident long before the
first C standard. It isn't relevant to what I was saying whether
unions were designed that way or not.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Nov 20 05:59AM -0800


>> Undefined behavior is a classification; it doesn't have effects.
 
> You managed to read 5 words?
> I meant [...]
 
If you can't be bothered to say what you mean in the first
place, don't expect people to waste their time trying to
figure out what you do mean.
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Nov 20 03:05PM +0100

On 20 Nov 2022 14:59, Tim Rentsch wrote:
 
> If you can't be bothered to say what you mean in the first
> place, don't expect people to waste their time trying to
> figure out what you do mean.
 
It's silly of you to pretend that you read just the first 5 words of a
sentence.
 
Even more silly to turn that around and demand that any contributor here
should sum up what they mean in the first 5 words of each sentence,
presumably with the rest of each sentence clarifying the first 5 words.
 
That position reminds me of Molbo-land, Moronia, Infantilia and other
such places.
 
 
- Alf
Tim Rentsch <tr.17687@z991.linuxsc.com>: Nov 20 07:22AM -0800

>> figure out what you do mean.
 
> It's silly of you to pretend that you read just the first 5 words of a
> sentence.
 
I am neither claiming nor pretending that I read only the first
five words of Tiib's comment. Those words are simply all that I
was responding to.
 
When given a bad omelette, I don't need to eat the whole thing to
discover it is bad.
 
> [...]
 
The rest of what you wrote seems irrelevant since your initial
assumption was wrong. In most cases it's better if you don't
read things into what I say that aren't there.
"Öö Tiib" <ootiib@hot.ee>: Nov 20 08:40AM -0800

On Sunday, 20 November 2022 at 17:23:06 UTC+2, Tim Rentsch wrote:
> > sentence.
> I am neither claiming nor pretending that I read only the first
> five words of Tiib's comment.
 
You left such impression. And improved it by saying that if 5
first words do not manage to say everything, then you should
not read rest of the sentence.
 
>> Those words are simply all that I was responding to.
 
Your response only misrepresented these five words.
 
 
> When given a bad omelette, I don't need to eat the whole thing to
> discover it is bad.
 
Look who's talking? What you post is mixture of lies,
misrepresentations and other sad garbage. Can be you have
nothing better to do but that is not my fault.
 
Michael S <already5chosen@yahoo.com>: Nov 19 03:27PM -0800

On Sunday, November 20, 2022 at 1:13:37 AM UTC+2, Öö Tiib wrote:
> > significantly harder.
> Pointer can be null, so everywhere it is passed has to check that it is
> not null and that gets quite repetitive to do after a while.
 
If you specified in the docs for your function that it can't take null
then you don't have to check for null.
Paavo Helde <eesnimi@osa.pri.ee>: Nov 20 01:28AM +0200

20.11.2022 01:27 Michael S kirjutas:
>> not null and that gets quite repetitive to do after a while.
 
> If you specified in the docs for your function that it can't take null
> then you don't have to check for null.
 
That's what a reference is for. It's self documenting.
"Öö Tiib" <ootiib@hot.ee>: Nov 19 03:33PM -0800

On Sunday, 20 November 2022 at 01:18:59 UTC+2, Chris M. Thomasson wrote:
> > not null and that gets quite repetitive to do after a while.
 
> Or, a lib writer can say passing a null pointer into function void*
> foo(void*) will result in undefined behavior.
 
So caller has to check, that is even worse violation of DRY as a function is
usually called from multiple places. Meanwhile lib writer can accept a
reference and then the check is needed on neither side.
Michael S <already5chosen@yahoo.com>: Nov 19 03:35PM -0800

On Sunday, November 20, 2022 at 12:38:14 AM UTC+2, Paavo Helde wrote:
> yourself")? Because with pointers you need to consider and repeat the
> fact that you are calling via a pointer at each call site, with
> references this is not so.
 
As I said, "except if you consider & here or * there as repeating yourself."
I don't. Also, even those who considered it repeating would agree that
it is non dangerous sort of repeating, because each time you did it wrong
compiler will catch you.
 
> I agree the code might be hard to understand if references or pointers
> are abused for implementing "output parameters".
 
You mean tuples?
May be, they should be used more, but syntax is rather ugly.
Even pairs look ugly.
 
 
> Also, if you say presence of references is what makes C++ hard to
> understand, I start to suspect you haven't seen half of C++ yet. Look up
> any template code posts from Bonita, for starters ;-)
 
Of course, I recognize that references are a small nuisance relatively
to 100 other features in C++, including 75 features that considered
god-send by "modern C++" enthusiasts.
Michael S <already5chosen@yahoo.com>: Nov 19 03:36PM -0800

On Sunday, November 20, 2022 at 1:33:16 AM UTC+2, Öö Tiib wrote:
> So caller has to check, that is even worse violation of DRY as a function is
> usually called from multiple places. Meanwhile lib writer can accept a
> reference and then the check is needed on neither side.
 
No, caller does not have to check, because caller knows that he passes non-null.
"Öö Tiib" <ootiib@hot.ee>: Nov 19 03:43PM -0800

On Sunday, 20 November 2022 at 01:36:50 UTC+2, Michael S wrote:
> > usually called from multiple places. Meanwhile lib writer can accept a
> > reference and then the check is needed on neither side.
> No, caller does not have to check, because caller knows that he passes non-null.
 
About reference it is known that it is not null but about pointer it is known only
after checking ... like if the caller is he or she takes checking.
Michael S <already5chosen@yahoo.com>: Nov 19 03:51PM -0800

On Sunday, November 20, 2022 at 1:43:28 AM UTC+2, Öö Tiib wrote:
> > No, caller does not have to check, because caller knows that he passes non-null.
> About reference it is known that it is not null but about pointer it is known only
> after checking ... like if the caller is he or she takes checking.
 
No. in code below caller does non need to check anything.
int bar;
foo(&bar);
"Öö Tiib" <ootiib@hot.ee>: Nov 19 05:57PM -0800

On Sunday, 20 November 2022 at 01:51:19 UTC+2, Michael S wrote:
 
> No. in code below caller does non need to check anything.
> int bar;
> foo(&bar);
 
That function foo there is done weirdly. Why it wasn't done without using neither
pointer nor reference? Like:
 
int bar = foo();
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Nov 19 07:56PM -0800

On 11/19/2022 5:57 PM, Öö Tiib wrote:
 
> That function foo there is done weirdly. Why it wasn't done without using neither
> pointer nor reference? Like:
 
> int bar = foo();
 
Because foo takes a pointer to an int that _shall_ not be a nullptr.
"Öö Tiib" <ootiib@hot.ee>: Nov 20 03:47AM -0800

On Sunday, 20 November 2022 at 05:56:28 UTC+2, Chris M. Thomasson wrote:
> > pointer nor reference? Like:
 
> > int bar = foo();
 
> Because foo takes a pointer to an int that _shall_ not be a nullptr.
 
I mean the int pointed at must be present but may be uninitialized so it is
lot more logical to have it as return value.
Michael S <already5chosen@yahoo.com>: Nov 20 04:24AM -0800

On Sunday, November 20, 2022 at 1:47:53 PM UTC+2, Öö Tiib wrote:
 
> > Because foo takes a pointer to an int that _shall_ not be a nullptr.
> I mean the int pointed at must be present but may be uninitialized so it is
> lot more logical to have it as return value.
 
This was an example intended to illustrate *one* point.
It was not an attempt to justify a passing of parameters by pointer/reference
vs other methods, but illustration of absence of material difference between
pointer and reference in this case and of weakness of your argument about need
to check for null by caller.
Normally, you are well capable of critical thinking, but in this particular
case it seems like you copied argument from bad beginner's book without giving
it your own thought.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Nov 20 05:48AM -0800

>> are out of your control! Then people that are going to read and comprehend
>> your code will be thankful.
 
> Aren't most languages similar to C at the level of virtual machine?
 
No. Many are. Many are not.
"Öö Tiib" <ootiib@hot.ee>: Nov 20 06:32AM -0800

On Sunday, 20 November 2022 at 14:24:38 UTC+2, Michael S wrote:
> > I mean the int pointed at must be present but may be uninitialized so it is
> > lot more logical to have it as return value.
 
> This was an example intended to illustrate *one* point.
 
It did not do that very well as it looked like badly designed interface.
 
> vs other methods, but illustration of absence of material difference between
> pointer and reference in this case and of weakness of your argument about need
> to check for null by caller.
 
Where did I claim that there do not exist such circumstances where we know
that some pointer can't be null? Reference communicates that situation better
and with less stars to type. Library whose documentation tells that lot of its
usages are undefined behavior is low quality library.
 
The whole reason of languages like Rust winning is that in real application
every C++ module has to be maximally paranoid with explicit and very
repetitive code about shit feed to it. Otherwise app crashes in their module,
bug will be reported to them, and they have to analyze and explain to yet
another set of confused newbies that it was documented that the argument
should not be null.
 
> Normally, you are well capable of critical thinking, but in this particular
> case it seems like you copied argument from bad beginner's book without giving
> it your own thought.
 
There are no point in your argument. I have not used any raw pointers in
C++ code for more than 15 years. There was no need to write code for
that as smart pointers, optional, variant and array were in boost already
at 2005. After C++11 there are even less theoretical corner cases where
there might be need for pointers. So my library interface just does not
have any raw pointer arguments and you have aired zero reason why it
has to change.
"gdo...@gmail.com" <gdotone@gmail.com>: Nov 19 04:54PM -0800

the code comes from C++20 for programmers, a Deitel book
I tried to compile the following code:
 
// fig17_01.cpp
// Profiling sequential and parallel sorting with the std::sort algorithm.
 
#include <algorithm>
#include <chrono> // for timing operations
#include <execution> // for execution policies
#include <iostream>
#include <iterator>
#include <random>
#include <vector>
 
int main()
{
// set up random-number generation

std::random_device rd;
std::default_random_engine engine{rd()};
std::uniform_int_distribution ints{};
 
std::cout << "Creating a vector v1 to hold 100,000,000 ints\n";
std::vector<int> v1(100'000'000); // 100,000,000 element vector
 
std::cout << "Filling vector v1 with random ints\n";
std::generate(v1.begin(), v1.end(), [&](){return ints(engine);});
 
// copy v1 to create identical data sets for each sort demonstration

std::cout << "Copying v1 to vector v2 to create identical data sets\n";
std::vector v2{v1};

// <chrono> library features we'll use for timing

using std::chrono::steady_clock;
using std::chrono::duration_cast;
using std::chrono::milliseconds;
 
// sequentially sort v1

std::cout << "\nSorting 100,000,000 ints sequentially\n";
auto start1 { steady_clock::now() }; // get current time
std::sort(v1.begin(), v1.end()); // sequential sort
auto end1 { steady_clock::now() }; // get current time
 
// calculate and display time in milliseconds

auto time1{duration_cast<milliseconds>(end1 - start1)};
std::cout << "Time: " << (time1.count() / 1000.0) << " seconds\n";
 
// parallel sort v2

std::cout << "\nSorting the same 100,000,000 ints in parallel\n";
auto start2{steady_clock::now()}; // get current time
std::sort(std::execution::par, v2.begin(), v2.end()); // parallel sort
auto end2{steady_clock::now()}; // get current time
 
// calculate and display time in milliseconds

auto time2{duration_cast<milliseconds>(end2 - start2)};
std::cout << "Time: " << (time2.count() / 1000.0) << " seconds\n";
}
 
clang++ -std=c++2a fig17_01.cpp
g++ -std=c++2a fig17.01.cpp
 
I receive errors relating to std::execution::par
 
how do I compile this?
"Öö Tiib" <ootiib@hot.ee>: Nov 19 06:11PM -0800

> g++ -std=c++2a fig17.01.cpp
 
> I receive errors relating to std::execution::par
 
> how do I compile this?
 
You read the text of errors and make corrections based on those. It can
be some compiler switch (like -ltbb) is missing ... or it can be that your
toolchain is not set up properly.
"gdo...@gmail.com" <gdotone@gmail.com>: Nov 19 07:30PM -0800

> You read the text of errors and make corrections based on those. It can
> be some compiler switch (like -ltbb) is missing ... or it can be that your
> toolchain is not set up properly.
 
using g++:
 
fig17_01.cpp:53:22: error: no member named 'execution' in namespace 'std'; did you mean 'exception'?
std::sort(std::execution::par, v2.begin(), v2.end()); // parallel sort
~~~~~^~~~~~~~~
exception
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/exception:99:29: note: 'exception' declared here
class _LIBCPP_EXCEPTION_ABI exception
^
fig17_01.cpp:53:33: error: no member named 'par' in 'std::exception'
std::sort(std::execution::par, v2.begin(), v2.end()); // parallel sort
~~~~~~~~~~~~~~~~^
2 errors generated.
 
 
using clang++:
 
fig17_01.cpp:53:22: error: no member named 'execution' in namespace 'std'; did you mean 'exception'?
std::sort(std::execution::par, v2.begin(), v2.end()); // parallel sort
~~~~~^~~~~~~~~
exception
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/exception:99:29: note: 'exception' declared here
class _LIBCPP_EXCEPTION_ABI exception
^
fig17_01.cpp:53:33: error: no member named 'par' in 'std::exception'
std::sort(std::execution::par, v2.begin(), v2.end()); // parallel sort
~~~~~~~~~~~~~~~~^
2 errors generated.
 
 
so <execution> has been included. but apparently it's not there. so it must be as you say, something, some library, needs to be -I included in the compile command?
Paavo Helde <eesnimi@osa.pri.ee>: Nov 20 10:10AM +0200

> g++ -std=c++2a fig17.01.cpp
 
> I receive errors relating to std::execution::par
 
> how do I compile this?
 
Compiles fine with g++ 10.2. Maybe you have too old gcc. If it doesn't
have -std=c++20 and only has -std=c++2a, then it's probably already a
sign it's too old.
"gdo...@gmail.com" <gdotone@gmail.com>: Nov 20 01:47AM -0800

Xcode 14.1, set target 20
 
GNU++20 [-std=gnu++20]
Bonita Montero <Bonita.Montero@gmail.com>: Nov 20 11:37AM +0100

Here's an example of std::sort with parallel execution
as well as single threaded, especially written for you:
 
#include <iostream>
#include <algorithm>
#include <execution>
#include <vector>
#include <random>
#include <chrono>
#include <charconv>
 
using namespace std;
using namespace chrono;
 
int main( int argc, char **argv )
{
if( argc < 2 )
return EXIT_FAILURE;
size_t n;
if( from_chars_result fcr = from_chars( argv[1], argv[1] + strlen(
argv[1] ), n ); (bool)fcr.ec || *fcr.ptr )
return EXIT_FAILURE;
vector<size_t> vs( n );
mt19937_64 mt;
uniform_int_distribution<size_t> uid( 0, -1 );
for( size_t &s : vs )
s = uid( mt );
auto start = high_resolution_clock::now();
if( argc > 2 )
sort( execution::parallel_policy(), vs.begin(), vs.end() );
else
sort( vs.begin(), vs.end() );
cout << n << ": " <<
duration_cast<nanoseconds>(high_resolution_clock::now() - start).count()
/ 1.0e9 << endl;
}
 
The first parameter is the number of elements in the vector to be
sorted. If there's an arbitrary second parameter the vector is sorted
on all processor cores.
Bonita Montero <Bonita.Montero@gmail.com>: Nov 20 12:19PM +0100

This modified program shows at which point parallel sorting
becomes more efficient than single-threaded sorting. For my
Zen2-CPU this is 0x1000 elements.
 
#include <iostream>
#include <algorithm>
#include <execution>
#include <vector>
#include <random>
#include <chrono>
#include <charconv>
 
#if defined(_MSC_VER)
#pragma warning(disable: 4996)

No comments: