Monday, December 14, 2015

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

JiiPee <no@notvalid.com>: Dec 13 12:43PM

I know that using different types, like enums, helps here as you cannot
pass a Cat enum to a Dog enum. But the problem comes when we must use
the same type variables (like strings in the example). But creating
different new types just for making the initialization work is a bit too
much to ask, isnt it?
JiiPee <no@notvalid.com>: Dec 13 12:38PM

We have:
 
class Person
{
public:
Person(string firstName, string secondName);
void setFirstName(string firstName);
void setsecondName(string firstName);
...
data members....
};
 
Now, If I create an object and initialize, normally we do:
 
1)
Person driver("John", "Smith");
 
But we could also do:
2)
Person driver;
driver.setFirstName("John");
driver.setsecondName("Smith");
 
Now, I know everybody says 1) should be done. And I know the benefits...
but.. am I also right the 2) tells more accurately
which parameter you are setting? In 1) we cannot be sure (without
checking the documentation) that which one is the first name
and which one is the second name. So from the code 1) we cannot be sure
whether we should input John as a first argument or second.
Maybe the second name should be the first argument (one might think....
looking at the code)?
But in 2) its very clear that first name is set to John.
I think others have struggled with this same. So... what to do? Which
one is better? Do you agree that we have a proglem
in 1) that we cannot be sure by looking at the code only that John
should be passed as a first parameter?
 
Is there another way to initialize an object so that only looking at the
code its very clear that John is passed as a first name
(because in 1) that is not clear really)?
 
This is what i have been struggled many times.
Paavo Helde <myfirstname@osa.pri.ee>: Dec 13 07:53AM -0600

> driver.setFirstName("John");
> driver.setsecondName("Smith");
 
> Is there another way to initialize an object so that only looking at
the
> code its very clear that John is passed as a first name
> (because in 1) that is not clear really)?
 
About looking at the code: if I see "John" and "Smith" then for me it is
pretty clear which is which. If it isn't then one might use e.g.:
 
using FirstName = std::string;
using SecondName = std::string;
 
Person driver(FirstName("Malcolm"), SecondName("Robert"));
 
Actually it is more important to get these things correct when *writing*
the code. Fortunately, IDE-s have pretty much solved this problem
nowadays via parameter info tooltips.
 
Cheers
Paavo
JiiPee <no@notvalid.com>: Dec 13 01:58PM

On 13/12/2015 13:53, Paavo Helde wrote:
 
> Actually it is more important to get these things correct when*writing*
> the code. Fortunately, IDE-s have pretty much solved this problem
> nowadays via parameter info tooltips.
 
Actually I did not mean that its clear what is the input value. I meant
that it goes to a correct place. LIke in your example if the class was
defined in another way (second name must be the first argument):
 
class Person
{
public:
Person(string secondName, string firstName);
void setFirstName(string firstName);
void setsecondName(string firstName);
...
data members....
};
 
and you do your:
 
Person driver(FirstName("Malcolm"), SecondName("Robert"));
 
that would go wrong, isnt it? The problem with class initialization
contructors is that you do not know where to place a certain
argument.... you cannot see it from the code.
 
So we do not know whether the first name should be the first argument or
the second, that is the problem.
JiiPee <no@notvalid.com>: Dec 13 02:02PM

On 13/12/2015 13:53, Paavo Helde wrote:
> using FirstName = std::string;
> using SecondName = std::string;
 
> Person driver(FirstName("Malcolm"), SecondName("Robert"));
 
This is not my point (what you asnwer here) .... but even in your answer
it is not *forced* that we have to do like that - the compiler does not
give an error if you do:
 
Person driver(SecondName("Malcolm"), FirstName("Robert"));
 
So your solutions does not increase the safety of the code, i think.
 
But again, this is not my point (to rename something)... so please read my other post to see what was my initial proglem.
Wouter van Ooijen <wouter@voti.nl>: Dec 13 03:12PM +0100

Op 13-Dec-15 om 1:38 PM schreef JiiPee:
> code its very clear that John is passed as a first name
> (because in 1) that is not clear really)?
 
> This is what i have been struggled many times.
 
IMO this is a real problem: two or more parameteres of the same type,
where the order is significant.
 
Using different types for the arguments is of course a solution, but it
doesn't help in your case.
 
There was a recent language proposal for 'named parameter association',
but AFAIK it was reject by the C++ comittee because 'it does not solve a
real problem'. I strongly disagree.
 
For functions you could include the order of the parameters in the name:
 
some_function_first_last( "John", "Smith" )
 
but that does not work for constructors.
 
You could make the constructor private, and provide a friend function
with an appropriate name.
 
My preference would probably to do that, but do it for a specific 'name'
class, because your person class probably needs more arguments than just
the name, and a name is worth being a class of its own. (There is more
to names than just the first and last name: things inbetween, the
Russian patronymic, etc.)
 
Wouter van Ooijen
JiiPee <no@notvalid.com>: Dec 13 02:22PM

On 13/12/2015 14:12, Wouter van Ooijen wrote:
 
> There was a recent language proposal for 'named parameter
> association', but AFAIK it was reject by the C++ comittee because 'it
> does not solve a real problem'. I strongly disagree.
 
Yes, this sounds to me like a good new feature, really useful and I
would use it definitely. I like the enum class came with C++11, we need
something like that here.
 
I many times scratch my head when creating my classes... whether to use
a contructor or other ways. The old constructor way feels a bit unsafe
to me. Thats why I sometimes prefer to use struct arguments:
 
struct PersonDetails driverDetails;
driver.name = "John";
driver.surname = "Smith";
 
and then pass this to the object:
 
Person driver(driverDetails);
 
Is this a good idea? at least you can see what is happening there. But
obviously the problem is that I might forget to set the surname for
example. So that gives other problems, so its not a perfect solution
neither.
JiiPee <no@notvalid.com>: Dec 13 02:26PM

On 13/12/2015 14:12, Wouter van Ooijen wrote:
> For functions you could include the order of the parameters in the name:
 
> some_function_first_last( "John", "Smith" )
 
Yes that is one trick, but I personally do not like long function names
though. Also now the function name is depending on the parameters, so
its not independent name. So, I think I would prefer to do this other
one what you said.... to create a new class for first and second name.
JiiPee <no@notvalid.com>: Dec 13 02:32PM

On 13/12/2015 14:12, Wouter van Ooijen wrote:
> IMO this is a real problem: two or more parameteres of the same type,
> where the order is significant.
 
and obviously we have this same problem with normal functions when
passing argument to them.
But all programming languages have this same problem, so maybe we just
have to live with it :).
Wouter van Ooijen <wouter@voti.nl>: Dec 13 03:36PM +0100

Op 13-Dec-15 om 3:32 PM schreef JiiPee:
> passing argument to them.
> But all programming languages have this same problem, so maybe we just
> have to live with it :).
 
Named parameter association (Ada, Python, probably others I am not
famliar with) nicely solves this.
 
Wouter
Barry Schwarz <schwarzb@dqel.com>: Dec 13 06:41AM -0800


>Is there another way to initialize an object so that only looking at the
>code its very clear that John is passed as a first name
>(because in 1) that is not clear really)?
 
While you specifically address initialization in the definition of an
object, the same issue exists with any function call that takes more
than one argument. (For example, in stoi does the base come before or
after the index pointer?) Do you feel the need to address it that
situation also?
 
--
Remove del for email
Wouter van Ooijen <wouter@voti.nl>: Dec 13 03:45PM +0100

Op 13-Dec-15 om 3:26 PM schreef JiiPee:
> though. Also now the function name is depending on the parameters, so
> its not independent name. So, I think I would prefer to do this other
> one what you said.... to create a new class for first and second name.
 
Note that *I* suggested to create a class for *name*, which moves the
problem to that class. (As I said, name probably deserves to be a class
in its own right.)
 
But you could also create distinct types for firtsname, secondname, etc.
 
IMO longer function names are not a real problem. If you had named
parameter association, you would put the same semantic information in
the parameter names, so it is the same amount of typing, and only a
little more work in reading (because the names and the parameters are no
nicely grouped as they would using named parameter association).
 
// alas, not possible in C++
auto x = name(
first = "Wouter",
prefix = "van",
surname = "Ooijen"
);
 
// my least bad alternative
auto x = name_first_suffix_surname (
"Wouter",
"van",
"Ooijen"
);
 
IIRC there is something in boost to so somthing that looks like named
parameter association, but like a lot of boost it might not be worth the
trouble if you woulod only use it occasionally.
 
Wouter
 
Wouter
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 13 03:45PM +0100

On 12/13/2015 1:38 PM, JiiPee wrote:
> which parameter you are setting? In 1) we cannot be sure (without
> checking the documentation) that which one is the first name
> and which one is the second name.
 
You can name the arguments to a constructor in many ways.
 
One way is to use the FAQ's "named parameters idiom". Another way is to
use the Boost parameters library (but it's too complex for me, although
at one time I drooled when discovering the preprocessor hacks in there).
And a third way can be to simply name special argument types:
 
<code>
#include <string>
#include <utility> // std::move
using namespace std;
 
template< class Value, class Type_id_type >
class Box
{
private:
Value v_;
public:
auto ref() -> Value& { return v_; }
Box( Value v ): v_( move( v ) ) {}
};
 
using First_name = Box< wstring, struct First_name_id >;
using Last_name = Box< wstring, struct Last_name_id >;
 
class Person
{
private:
wstring first_name_;
wstring last_name_;
 
public:
auto first_name() const -> wstring { return first_name_; }
auto last_name() const -> wstring { return last_name_; }
 
void set( First_name value ) { first_name_ = move(
value.ref() ); }
void set( Last_name value ) { last_name_ = move(
value.ref() ); }
 
Person( First_name first_name, Last_name last_name )
: first_name_( move( first_name.ref() ) )
, last_name_( move( last_name.ref() ) )
{}
};
 
#include <iostream>
auto main() -> int
{
auto x = Person( First_name( L"Jii" ), Last_name( L"Pee" ) );
wcout << x.first_name() << " " << x.last_name() << "\n";
}
</code>
 
> [snip]
> This is what i have been struggled many times.
 
Well, I hope the above gave you some ideas! ;-)
 
 
Cheers & hth.,
 
- Alf
Wouter van Ooijen <wouter@voti.nl>: Dec 13 03:52PM +0100

> prefix = "van",
> surname = "Ooijen"
> );
 
In case anyone wonders why I didn't simply use
 
auto x = name(
first = "Wouter",
surname = "van Ooijen"
);
 
In the Nethlands we consider the surname NOT to include the prefix. Wgen
sorted alphabetically for instance, I would be found under the O. Yet
when writting, my 'second name' is still 'van Ooijen'.
 
To make matter even more interesting, IIRC our Southern neigbours the
Flemish (half of Belgium) *do* consider the prefix part of the surname,
so they would sort me under the 'v'.
 
Wouter
Paavo Helde <myfirstname@osa.pri.ee>: Dec 13 08:53AM -0600

JiiPee <no@notvalid.com> wrote in
 
>> Person driver(FirstName("Malcolm"), SecondName("Robert"));
 
> So we do not know whether the first name should be the first argument
> or the second, that is the problem.
 
Yes I guessed that much, but this was not what you asked in the first post.
 
As I mentioned, for me the IDE-s have solved the latter problem. When I
look at the code and do not know which argument should go first and which
the second then I just hover the mouse over the function name and it tells
me.
 
Cheers
Paavo
JiiPee <no@notvalid.com>: Dec 13 03:38PM

On 13/12/2015 14:41, Barry Schwarz wrote:
> than one argument. (For example, in stoi does the base come before or
> after the index pointer?) Do you feel the need to address it that
> situation also?
 
when i use those functions, i normally always check the documentation to
be sure about the order of the parameters
JiiPee <no@notvalid.com>: Dec 13 03:43PM

On 13/12/2015 14:45, Alf P. Steinbach wrote:
> Well, I hope the above gave you some ideas! ;-)
 
that looks complex, but I ll have to look at that
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 13 04:59PM

On Sun, 2015-12-13, JiiPee wrote:
> driver.setFirstName("John");
> driver.setsecondName("Smith");
 
> Now, I know everybody says 1) should be done. And I know the benefits...
 
Here ...
 
> But in 2) its very clear that first name is set to John.
> I think others have struggled with this same. So... what to do? Which
> one is better?
 
You answered that above. (1).
 
> code its very clear that John is passed as a first name
> (because in 1) that is not clear really)?
 
> This is what i have been struggled many times.
 
When I end up in that situation, I try to do a reality check.
 
Does it really matter? For example, I bet in a real program, new
Persons are created in one place (because you read them from the user
interface, or some input file) and then never modified (not the name,
anyway). If you get the construction wrong, you'll notice as soon as
you run the program.
 
But if I find that people never change names at runtime, I probably
don't want to implement (2) which enables you to do just that.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
JiiPee <no@notvalid.com>: Dec 13 06:33PM

Here they actually seem to give a lot of ways to do it...although they
do not seem all very practical:
 
https://marcoarena.wordpress.com/2014/12/16/bring-named-parameters-in-modern-cpp/
JiiPee <no@notvalid.com>: Dec 13 07:30PM

On 13/12/2015 18:54, Stefan Ram wrote:
> { double x; double y;
> ::std::cout << ::std::pow( x = 2, y = 3 )<< '\n'; }
 
> 8
 
oh but this is not we are talking about. We are talking about:
we have a function:
 
void createArray(int length, int capacity);
and it is called:
createArray(length=10, capacity=20);
 
so this:
createArray(len=10, capacity=20);
 
would give a compiler error because the first must be
length
David Brown <david.brown@hesbynett.no>: Dec 13 08:50PM +0100

On 13/12/15 16:11, Paavo Helde wrote:
> int f(int y, int x); // a legal redeclaration (currently)
 
> f(1,2); // no ambiguity
> f(x => 1, y => 2); // ???
 
There is currently a proposal to add named parameters to C++17, and it
would simply be illegal to use them if there were contradictory
declarations in scope. (The proposed syntax is slightly different, "f(x
: 1, y : 2);", but the principle is the same.)
 
I would like compilers to have such legal but contradictory
redeclarations as a common warning - there is no reason for them except
to confuse people using the code.
Melzzzzz <mel@zzzzz.com>: Dec 13 03:12PM +0100

On 13 Dec 2015 13:41:37 GMT
> ntdll.dll!RtlUserThreadStart
 
> What's this? My program spends most of its time to »wait
> for multiple objects«??
 
It's a Windows thing.
 
 
> I do not call »_misaligned_access« directly in my SlowProgram!
 
> Is this the processor causing an interrupt due to misaligned
> data very often?
 
Nope. You get align exceptions on x86 only if loading SSE vectors.
 
 
> I used to believe that C++ would align my vector of ints so
> that this doesn't happen.
 
Try with custom allocator and see.
mark <mark@invalid.invalid>: Dec 13 04:16PM +0100

On 2015-12-13 14:41, Stefan Ram wrote:
> that this doesn't happen.
 
> Is it because my CPU is called a »64-bit CPU« and the ints
> are 32-bit objects? So, should I try to use 64-bit objects?
 
There is no penalty on current Intel/AMD x64 CPUs for unaligned access.
There never was a significant one and no interrupts or hardware
exceptions are generated.
 
Chances are 99.999% that your vector is 8-byte aligned to begin with
(unless you went out of your way to set up some weird memory allocator).
You can cast vector.data() to uintptr_t to check the alignment - on x64,
the address space is as straightforward as it gets. A pointer is
basically a 64-bit unsigned int.
 
Your stack trace may well be from a GUI thread or a thread pool where a
worker has nothing to do.
 
Are you sure this a stack trace from your collection processing code in
the first place?
Paavo Helde <myfirstname@osa.pri.ee>: Dec 13 10:27AM -0600

ram@zedat.fu-berlin.de (Stefan Ram) wrote in news:slow-vector-
> ntdll.dll!RtlUserThreadStart
 
> What's this? My program spends most of its time to »wait
> for multiple objects«??
 
This stack looks like some auxiliary service thread possibly created by
gcc itself. Find your actual working thread and study it instead.
 
Note also that it is not guaranteed at all that a "stack monitor" is able
to display correct stacks, especially for optimized compilations. In my
experience they are often at least partially garbage.
 
Cheers
Paavo
ram@zedat.fu-berlin.de (Stefan Ram): Dec 13 01:41PM

I have a vector filled with about 16000 unsigned ints,
which seem to have 4 bytes each here.
 
/* at file scope, after »using NUMBER = unsigned int;«: */
 
::std::vector<NUMBER> collection;
 
I have an »inner loop«, where no new entries are added to
the vector and the result of collection.data() is accessed
as an array. It searches through subsets of the array, and
therefore the accesses might be somewhat irregular (for the
prefetcher). I wondered whether that array still fits in some
cache.
 
Now, I looked at the program with a stack monitor. It shows
always (whenever probed) something like this, under Windows:
 
ntoskrnl.exe!KeWaitForMultipleObjects
ntoskrnl.exe!KeAcquireSpinLockAtDpcLevel
ntoskrnl.exe!KeWaitForSingleObject
ntoskrnl.exe!_misaligned_access
ntoskrnl.exe!_misaligned_access
ntoskrnl.exe!_misaligned_access
SlowProgram.exe
SlowProgram.exe
SlowProgram.exe
SlowProgram.exe
SlowProgram.exe
kernel32.dll!BaseThreadInitThunk
ntdll.dll!RtlUserThreadStart
 
What's this? My program spends most of its time to »wait
for multiple objects«??
 
I do not call »_misaligned_access« directly in my SlowProgram!
 
Is this the processor causing an interrupt due to misaligned
data very often?
 
I used to believe that C++ would align my vector of ints so
that this doesn't happen.
 
Is it because my CPU is called a »64-bit CPU« and the ints
are 32-bit objects? So, should I try to use 64-bit objects?
 
What is happening here?
 
If I could understand this, maybe then I could find a way
to make my program's inner loop faster.
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: