- Object initialization confusion - 21 Updates
- Alignment, can I do something about it? - 3 Updates
- Alignment, can I do something about it? - 1 Update
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:
Post a Comment