- Is there benefit to having both class enum and "traditional" enum (other than backward compatibility)? - 1 Update
- Integer to Ustring - 7 Updates
- std::map operator [] problems - 9 Updates
- How to portably cast from void* to int - 3 Updates
- getting at value_type? - 2 Updates
- Zeroing in the constructor - 2 Updates
- How to portably cast from void* to int - 1 Update
"K. Frank" <kfrank29.c@gmail.com>: Jun 17 06:18AM -0700 Hello Group! If one were to redesign c++ without backward compatibility as a goal, would it make sense to include both class enum and old-fashioned (pre-c++11) enum? Are there use cases where plain enum is better (enough better to be worth the weight of having two different kinds of enum in the language)? Thanks. K. Frank |
"Jason C. McDonald" <indeliblebluepen@nospam.invalid>: Jun 16 03:18PM -0700 I am trying to write a function that can convert an integer to its equivalent Ustring (or, arguably, most any string class), without having to rely on the STL or third-party libraries. I'm also wanting to use math as much as possible, so I don't have to use massive conditionals or data structures. This code IS working quite well, but I feel like it can be improved. Any feedback, improvements, or whatnot? --- Glib::ustring int_to_ustring(int num) { bool neg = false; int sub = 0; char digit; //This is what we'll return. Glib::ustring str = ""; //If number is 0, the math won't work. Just return the string "0". if(num == 0) { str = "0"; return str; } //Else, if the number is negative... else if(num < 0) { //Store that information and make the number positive. neg = true; num = abs(num); } //Determine place value. int pv = 0; do { //Divide by a power of ten and trunicate decimal. sub = num / pow(10, pv); //Increase pv. pv++; } //If we got zero, then we've overshot place value. while(sub != 0); //NOTE: The above seems to sometimes make the place value two-too-large? //Loop backwards through the place values. for(pv; pv >= 0; pv--) { //std::cout << "10^" << pv << "::" << num; sub = num / pow(10, pv); num -= sub*(pow(10, pv)); //std::cout << " --> " << "[" << sub << "]" << num << std::endl; if(sub < 0 || sub > 10) { //Throw an error. I'm just using this as a placeholder. std::cout << "Something went really weird." << std::endl; } //The char code for the digit is always 48 more than the digit. digit = sub + 48; //If this isn't a leading zero... if(!(str == "" && digit == '0')) { //This is the best way to push a char to a ustring. str.insert(str.end(), digit); } } //If that number was negative, insert the negative sign. if(neg) str.insert(str.begin(), '-'); return str; } -- The number of ways in which code can be potentially screwed up is theoretically infinite. www.indeliblebluepen.com |
Christopher Pisz <nospam@notanaddress.com>: Jun 16 05:48PM -0500 On 6/16/2015 5:18 PM, Jason C. McDonald wrote: > data structures. > This code IS working quite well, but I feel like it can be improved. Any > feedback, improvements, or whatnot? 1) what is a UString? 2) what's wrong with the STL? 2a) What's wrong with std::string? 3) Why would you want to use math for something that can be done a few lines with the STL? 4) Massive conditionals and data structures? huh? All of the improvements I would suggest would be to throw away the aforementioned constraints. You really shouldn't make constraints without very good reason. I can't say that I've heard a good reason for using C++ without the STL to date. Your statement is like, "I want to do things better, but I can't use the better way of doing things to do it." > str.insert(str.begin(), '-'); > return str; > } Here is my version: //------------------------------------------------------------------------------ std::string IntToString(const long long & value) { std::ostringstream converter; converter << value; return converter.str(); } //------------------------------------------------------------------------------ std::string UIntToString(const unsigned long long & value) { std::ostringstream converter; converter << value; return converter.str(); } //-------------------------------------------------------------------------------------------------- int StringToInt(const std::string & value) { int result; std::istringstream converter(value); if( (converter >> result).fail() ) { std::ostringstream msg; msg << "Could not convert string: \"" << value << "\" to int"; throw Shared::Exception(__FILE__, __LINE__, msg.str()); // Use your favorite exception here } return result; } //-------------------------------------------------------------------------------------------------- boost::optional<int> StringToNullableInt(const std::string & value) { if( value.empty() ) { return boost::none; } return Shared::StringToInt(value); } etc. etc. Which looks more readable and maintainable? Feel free to use the C library functions instead of you are more interested in saving the bit of performance over using streams, but are sure to do the proper error checking. Another alternative is boost::lexical_cast. EDIT: After Googling ustring, I'd opt to use std::string internally and call the glib conversions when I needed UTF-8 only when a call was expecting UTF-8. I am not a fan of "X uses unicode, so let's use different string representations in our entire program." It makes messes. Furthermore, it looks like yer glib::ustring has stream operators anyway, so you can use those in the same manner. -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
"Jason C. McDonald" <indeliblebluepen@nospam.invalid>: Jun 16 04:13PM -0700 On 06/16/2015 03:48 PM, Christopher Pisz wrote: >> This code IS working quite well, but I feel like it can be improved. Any >> feedback, improvements, or whatnot? > 1) what is a UString? Glib::ustring is a string which has full unicode support and is a required component of the the gtkmm library, which runs a HUGE number of GUIs. > 2) what's wrong with the STL? Nothing inherently. It's a project-specific decision, and I'm not the first to make it. It's a matter of efficiency w/ some hardware, i.e. older machines. It is rather common for game engine designers to be VERY selective about what parts of STL to use. Besides, if you're using ustring, using stringstream is YET ANOTHER import, so your program just got bigger arbitrarily. > 2a) What's wrong with std::string? Nothing inherently, except I need to use Ustring (see my reply to #1). Also, string is inefficient in some situations. Argue w/ Jason Gregory on that point. (author of "Game Engine Architecture".) > 3) Why would you want to use math for something that can be done a few > lines with the STL? See above. Also, the question "why would you want to do it differently" should set off alarm bells here. As soon as we stop trying to find more efficient ways to do things, we start stagnating. I never rely blindly on existing solutions. I often recreate functionality, to see if I can improve on it. (Also, gives me a good code recipe with which to do this in another language.) Besides that, just using someone else's solution without understanding it is feeding into that infamous layers of abstraction problem that Joel Spolsky pointed out. > 4) Massive conditionals and data structures? huh? The quickest hack solution to this would be using a large if statement or an array. Unnecessary conditionals waste CPU cycles, and unnecessary data structures waste RAM. > using C++ without the STL to date. > Your statement is like, "I want to do things better, but I can't use the > better way of doing things to do it." Careful of jumping to that conclusion. STL is not the for-all-end-all. I'm not against using it, but if a simple task such as this requires me to import an entire STL header, I'd prefer to wrap my own if I can come close to efficiency. It yields a smaller program. I should mention that I am targeting older systems as well as new. (Older, as in 256MB RAM or less and 20-yr-old processors, which accounts for a surprisingly large number of school computer labs, my target user group.) -- The number of ways in which code can be potentially screwed up is theoretically infinite. www.indeliblebluepen.com |
Christopher Pisz <nospam@notanaddress.com>: Jun 16 06:24PM -0500 On 6/16/2015 6:13 PM, Jason C. McDonald wrote: > I am targeting older systems as well as new. (Older, as in 256MB RAM or > less and 20-yr-old processors, which accounts for a surprisingly large > number of school computer labs, my target user group.) Fair enough. Just be careful. It's been my experience thus far that every time I run into a code block that tries to "do what the STL does, but better" it not only performed worse, but filled up the bug tracker as well. Not that you are one of those people, but there exists a crowd that takes that stance, whom never performance tested in a satisfactory manner, and/or whom cannot compete, testing wise, with the millions of users calling the STL vs the 5-20 calling their code. I cannot comment on what to do with 20 year old computers, because I was still learning what poke 53280,0 meant on my c64 and sneaking out of my bedroom at night to play Elite in my batman PJs. -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
"Jason C. McDonald" <indeliblebluepen@nospam.invalid>: Jun 16 04:44PM -0700 On 06/16/2015 04:24 PM, Christopher Pisz wrote: > that takes that stance, whom never performance tested in a satisfactory > manner, and/or whom cannot compete, testing wise, with the millions of > users calling the STL vs the 5-20 calling their code. Absolutely. There's dangers on both sides of the line, really. Glib and ICU are two libraries that reportedly succeed at out-performing STL, though I haven't tested that claim personally yet. I'm using Glib more-or-less out of necessity, since I'm relying to gtkmm for GUI building. I tend to be wary of code libraries by default. I'm actually designing a language at the moment, so that's the other reason I'm in "recreate functionality" mode. > I cannot comment on what to do with 20 year old computers, because I was > still learning what poke 53280,0 meant on my c64 and sneaking out of my > bedroom at night to play Elite in my batman PJs. Heck, at the moment, I can't either. All I know is to be near-pathologically stingy with memory and CPU cycles. [Ahhhh, Elite. Side note, have you seen the open-source Elite-clone, Oolite? Quite impressive.] -- The number of ways in which code can be potentially screwed up is theoretically infinite. www.indeliblebluepen.com |
"Jason C. McDonald" <indeliblebluepen@nospam.invalid>: Jun 16 05:24PM -0700 On 06/16/2015 03:18 PM, Jason C. McDonald wrote: > data structures. > This code IS working quite well, but I feel like it can be improved. Any > feedback, improvements, or whatnot? Following up on my own, thanks to a Stack Overflow discussion (http://stackoverflow.com/a/30880365/472647). Apparently, no one online bothered to mention the bright-blazingly-obvious solution using Glib... Glib::ustring text = Glib::ustring::format(123456); However, I still would like feedback on mine, as there is still those who desire to do something like this for custom string classes without using third-party libraries. Just ignore Glib::ustring, and insert <your custom class> if you want to give feedback. -- The number of ways in which code can be potentially screwed up is theoretically infinite. www.indeliblebluepen.com |
Christian Gollwitzer <auriocus@gmx.de>: Jun 17 09:20AM +0200 Am 17.06.15 um 02:24 schrieb Jason C. McDonald: > (http://stackoverflow.com/a/30880365/472647). Apparently, no one online > bothered to mention the bright-blazingly-obvious solution using Glib... > Glib::ustring text = Glib::ustring::format(123456); for sure you are not the first person wanting to print data to ustring, so I'm not very surprised you found a ready-made number formatter already. > However, I still would like feedback on mine, as there is still those > who desire to do something like this for custom string classes without > using third-party libraries. Your algorithm is a bit strange. Formatting integers is usually done by the divide and mod algorithm, which works like this if (i<0) { print "-"; i=-i } i=12345678 while i { print i % 10 i = i/10 } Afterwards you reverse the digits. Calling a power library function for each digit and doing subtracts etc. will likely be much slower than the repeated div/mod apporach shown here. "pow" is a floating point function. Your algorithm does repeated conversion between integer and double, which is not going to help either accuracy or speed. > Just ignore Glib::ustring, and insert <your > custom class> if you want to give feedback. I'd get a decent implementation from somewhere else instead of writing my own. It becomes an order of magnitude more complex if you are dealing with floating point numbers. Then you'll have to handle NaN, Inf etc. in addition to printing the normalized value. I wouldn't recommend to roll your own unless you implement the string library (and let me ask, why) Christian |
Christopher Pisz <nospam@notanaddress.com>: Jun 16 05:34PM -0500 I am getting a compiler error: Error 1 error C2678: binary '[' : no operator found which takes a left-hand operand of type 'const std::map<int,std::vector<std::string,std::allocator<_Ty>>,std::less<_Kty>,std::allocator<std::pair<const _Kty,std::vector<_Ty,std::allocator<_Ty>>>>>' (or there is no acceptable conversion) c:\users\christopher.pisz\documents\visual studio 2013\projects\test\test\main.cpp 12 1 Test With the following test: #include <map> #include <vector> void Foo(const std::map<int, std::vector<std::string> > & theMap) { // If the map does not contain a value for the key // I'd expect it to make an empty vector and return that // but instead, I get a compiler error const std::vector<std::string> stuff = theMap[1]; } int main() { std::map<int, std::vector<std::string> > myMap; std::vector<std::string> myVector; myVector.push_back("Hello"); myVector.push_back("Good Bye"); myMap[1] = myVector; Foo(myMap); return 0; } I thought operator[] inserted a default constructed value if one did not exist for the given key. I'd expect "Stuff" to be an empty vector, but I get a compiler error instead. Where did I go wrong here? -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
Melzzzzz <mel@zzzzz.com>: Jun 17 12:48AM +0200 On Tue, 16 Jun 2015 17:34:05 -0500 > // but instead, I get a compiler error > const std::vector<std::string> stuff = theMap[1]; > } Get rid of the "const". |
Christopher Pisz <nospam@notanaddress.com>: Jun 16 05:49PM -0500 On 6/16/2015 5:48 PM, Melzzzzz wrote: >> const std::vector<std::string> stuff = theMap[1]; >> } > Get rid of the "const". #include <iostream> #include <map> #include <vector> void Foo(const std::map<int, std::vector<std::string> > & theMap) { // If the map does not contain a value for the key // I'd expect it to make an empty vector and return that // but instead, I get a compiler error std::vector<std::string> stuff = theMap[1]; } int main() { std::map<int, std::vector<std::string> > myMap; std::vector<std::string> myVector; myVector.push_back("Hello"); myVector.push_back("Good Bye"); myMap[1] = myVector; Foo(myMap); return 0; } Same error. Were you referring to a different const? -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
Melzzzzz <mel@zzzzz.com>: Jun 17 12:50AM +0200 On Tue, 16 Jun 2015 17:49:45 -0500 > } > Same error. > Were you referring to a different const? void Foo(/* this const*/ std::map<int, std::vector<std::string> > & theMap) |
Christopher Pisz <nospam@notanaddress.com>: Jun 16 06:01PM -0500 On 6/16/2015 5:50 PM, Melzzzzz wrote: >>>> const std::vector<std::string> stuff = theMap[1]; >>>> } >>> Get rid of the "const". SNIP > void Foo(/* this const*/ std::map<int, std::vector<std::string> > & > theMap) Oh I see...Is it because of the scenario where the key doesn't exist, it would have to default construct a vector, which in turn would alter the map? -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
Melzzzzz <mel@zzzzz.com>: Jun 17 01:02AM +0200 On Tue, 16 Jun 2015 18:01:18 -0500 > Oh I see...Is it because of the scenario where the key doesn't exist, > it would have to default construct a vector, which in turn would > alter the map? Exactly. |
Barry Schwarz <schwarzb@dqel.com>: Jun 16 04:09PM -0700 On Tue, 16 Jun 2015 17:34:05 -0500, Christopher Pisz >{ > // If the map does not contain a value for the key > // I'd expect it to make an empty vector and return that This part of your expectation is a run time situation, not a compile time determination. > // but instead, I get a compiler error > const std::vector<std::string> stuff = theMap[1]; It compiles fine on my system if you remove the "const" from Foo's parameter. The same compiler diagnostic is issued even if you remove the "&". So the fact that the parameter is a reference is not the problem. It apparently has something to do with the "const". I guess the [] operator is not defined for const map. It compiles fine with the const if you change theMap[1] to theMap.at(1) in the assignment statement. >I thought operator[] inserted a default constructed value if one did not >exist for the given key. I'd expect "Stuff" to be an empty vector, but I >get a compiler error instead. Where did I go wrong here? You are mixing run time and compile time "performance". -- Remove del for email |
Christopher Pisz <nospam@notanaddress.com>: Jun 16 06:14PM -0500 On 6/16/2015 6:02 PM, Melzzzzz wrote: > Exactly. Excellent. Thanks for the help. In that case, I think I want to use this alternative, so I can promise the caller I won't alter their map. No sense in using find here, as far as I can tell. I've never used the "at" member though. void Foo(const std::map<int, std::vector<std::string> > & theMap) { std::vector<std::string> & stuff = std::vector<std::string>(); try { stuff = theMap.at(1); } catch(std::out_of_range &) { // Leave the vector empty } // Iterate over the elements and do things. } -- I have chosen to troll filter/ignore all subthreads containing the words: "Rick C. Hodgins", "Flibble", and "Islam" So, I won't be able to see or respond to any such messages --- |
Paavo Helde <myfirstname@osa.pri.ee>: Jun 17 01:09AM -0500 Christopher Pisz <nospam@notanaddress.com> wrote in > // I'd expect it to make an empty vector and return that > // but instead, I get a compiler error > const std::vector<std::string> stuff = theMap[1]; void Foo(const std::map<int, std::vector<std::string> > & theMap) { auto iter = theMap.find(1); const std::vector<std::string> stuff = (iter==theMap.end()? std::vector<std::string>(): iter->second); } hth Paavo |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 17 12:42AM +0100 On Tue, 16 Jun 2015 21:37:00 +0100 Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote: [snip] > the conversion will work. (You do have to worry if the size of int > is larger than the size of void*, but I know of no implementation > where that is the case.) On looking it up I think on the last point I was too pessimistic. It seems to me that reinterpret casts of int->void*->int are obliged to work according to the standard - in other words, sizeof(int) cannot be larger than sizeof(void*) in a conforming implementation. In fact, it appears that sizeof(long long) cannot be larger than sizeof(void*): §5.2.10/4 of C++11: "A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined. [ Note: It is intended to be unsurprising to those who know the addressing structure of the underlying machine. — end note ]. ... ." §5.2.10/5 of C++11: "A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined. ... ." In the first sentence of §5.2.10/5 there is no qualification about sizes for the integer->pointer conversion. The reverse conversion does have a size qualification. Chris |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 17 01:12AM +0100 On Wed, 17 Jun 2015 00:42:48 +0100 > work according to the standard - in other words, sizeof(int) cannot be > larger than sizeof(void*) in a conforming implementation. In fact, it > appears that sizeof(long long) cannot be larger than sizeof(void*): [snip] Well, whatever the theory, it is not borne out by practice. On the 32-bit machines on which I have just now tested, sizeof(long long) certainly is larger than sizeof (void*). The first is 8 and the second is 4. But it is curious that the qualification about sizes is omitted in the standard for integral to pointer conversions. Chris |
Martin Shobe <martin.shobe@yahoo.com>: Jun 16 09:01PM -0500 On 6/16/2015 2:55 PM, Victor Bazarov wrote: > OK. Now consider this. It does so, and it gets called from other > functions of the same API some time later, and the local variable has > gone out of scope and its address contains garbage... Obviously, you have to keep it around for as long as the API needs it. >> much less? I think I detect a bit of hyperbole. > Not if the lifetime has to be managed across modules or beyond one API > call. Even then. The API, in order to be usable, should have documentation that tells you how long you have to keep it around. While I won't claim that every case is easy, I've never encountered one where it would be hard. >> } > Bad idea using C-style casts, that one of the points I failed to > deliver, I am guessing... I won't disagree about the use of C-style casts, it just wasn't important for my point so I didn't change it. Martin Shobe |
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 06:07PM -0400 On 6/16/2015 5:45 PM, Doug Mika wrote: > on the reference site, query vector: > http://www.cplusplus.com/reference/vector/vector/?kw=vector > when you scroll down it gives a list of Member Types. How can I know whether they are object members or class members? By RTFMing, maybe? V -- I do not respond to top-posted replies, please don't ask |
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 06:14PM -0400 On 6/16/2015 5:55 PM, Paavo Helde wrote: >> It's a member of the class, not a member of an object. > Static member functions are also members of the class, yet can be called > on an object. Just saying... Yes, why don't we just unify anything that sounds similar? I guess it was too much to ask of the compiler creators to allow types to be figured out from an expression, like in a declaration: (object1 @ object2).sometypename variablename; (here 'object1 @ object2' is an expression that yields another object, of some type. The Standard writers agreed that to simplify the parsing (again, I'm guessing here) you need to write decltype(...) :: sometypename ... since 'decltype' yields a *type*, and not an instance, you need to use the scope resolution operator to get to a member type. V -- I do not respond to top-posted replies, please don't ask |
Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 05:06PM -0400 On 6/16/2015 5:02 PM, Richard wrote: >> IOW, 'new foo' ignores the individuals member initializers while 'new >> foo{}' uses those. > I don't think this is quite right about 'new foo' as per above. You're likely right, and I wasn't reading the Standard carefully. I am guessing it mostly differs for the members that *don't have* an initializer specified for them. V -- I do not respond to top-posted replies, please don't ask |
legalize+jeeves@mail.xmission.com (Richard): Jun 16 09:13PM [Please do not mail me a copy of your followup] Noob <root@127.0.0.1> spake the secret code >On 16/06/2015 22:16, Noob wrote: >> What version of Visual C++ fully supports C++11? >Looking bleak. Not really. Most programmers are not going to need every single C++11 feature in the core language, never mind all the features in the library. >to be completely fixed in 2015 RTM. ...which is about to drop any day now. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
ram@zedat.fu-berlin.de (Stefan Ram): Jun 16 02:57PM >but this gives error when p is 64 bit and int 32 bit. >I can cast to long but long does not have to be 64 bit,either. >What do you suggest? uintptr_t 18.4.1 Header <cstdint> synopsis [cstdint.syn] But seriously, to take a step backwards and ask why this is necessary. |
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