- getting at value_type? - 4 Updates
- Avoid 'int' and associates. - 6 Updates
- operator+ - 5 Updates
- How to portably cast from void* to int - 7 Updates
- Zeroing in the constructor - 3 Updates
| Doug Mika <dougmmika@gmail.com>: Jun 16 02:13PM -0700 Why can't I do the following: #include <iostream> #include <string> using namespace std; template<typename T> struct C { using value_type=T; string name; int number; }; int main() { C<int> c1{"Michael", 1}; C<string> c2{"Suzanne",2}; c1.value_type x; //Line xx - doesn't work return 0; } Instead what I must do in line xx is decltype(c1)::value_type x;? Is value_type a member of c1? (just as is name) |
| Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 05:23PM -0400 On 6/16/2015 5:13 PM, Doug Mika wrote: > } > Instead what I must do in line xx is decltype(c1)::value_type x;? > Is value_type a member of c1? (just as is name) It's a member of the class, not a member of an object. V -- I do not respond to top-posted replies, please don't ask |
| Doug Mika <dougmmika@gmail.com>: Jun 16 02:45PM -0700 On Tuesday, June 16, 2015 at 4:23:18 PM UTC-5, Victor Bazarov wrote: > V > -- > I do not respond to top-posted replies, please don't ask In that case wondering whether you'd know: 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? |
| Paavo Helde <myfirstname@osa.pri.ee>: Jun 16 04:55PM -0500 Victor Bazarov <v.bazarov@comcast.invalid> wrote in news:mlq41d$2n3$2 >> Instead what I must do in line xx is decltype(c1)::value_type x;? >> Is value_type a member of c1? (just as is name) > 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... Cheers Paavo |
| legalize+jeeves@mail.xmission.com (Richard): Jun 16 02:59PM -0600 [Please do not mail me a copy of your followup] slp53@pacbell.net spake the secret code >Granted most of that code ran sans OS (it was the OS), and required >fixed types to map to various hardware registers. This is the situation where I think the size of the data really *does* matter and it's important to use sized types and not the implicit size of int, long, etc. Things like structures representing byte streams passed across the network (and you might do network-to-host byte reordering in place on that structure), raw byte streams read from or written to files, raw bytes transmitted between processes through shared memory segments and so-on. I've got some code im my open source project that doesn't use specifically sized types for some binary file I/O and it's a mess right because they used generic types. So I am certainly sympathetic to cases where it matters. My assertion is that it simply doesn't matter in *every* case. >run into many issues in the past porting software from 16-bit >ints to 32-bit ints (and from 32-bit longs to 64-bit longs), >I would never advocating using 'int' for anything. Here, I disagree. The size of every int in a program isn't a portability concern. What's important is deciding which variables need specific sizes and which don't.[*] I've seen code where the compiler's default size of an int was 16-bits and everywhere they wanted to iterate over containers or whatnot it was int16_t all over the place. Then you move to a compiler where the defaault size of an int is 32-bits. The fact that all those ints were marked as 16-bits is now erroneous and simply a distraction. How do you know which ones really needed to be 16-bits and which were 16-bits simply because that was the default size of an int? Forcing them all into a 16-bit straight jacket impedes portability instead of enhancing it. In other words, like most things in programming, it's a matter of good judgment. Simplistically applying a rule like "never use int" is opening up your skull and dumping your brains in the garbage. There is a time when specifically sized types are important. For most of the C++ I have worked on in the past 25 years, it was important in only a very few cases. Working on code where the team insisted on sizing every single named quantity in the application was tedious and yielded little to no value. I have done very little programming in embedded environments with strict resource limits and I can see how someone who spent 25 years in that environment would consider it indispensible that everything be specifically sized. So it varies with experience and problem domain. But this is just another reason to advocate for proper application of good judgment for your problem domain instead of adopting a simplistic rule. Even within a problem domain, things can change over time. Embedded processors today have access to many more resources than they did in the 80s when 64 users time shared out of 128KB of main memory and an embedded CPU was lucky to have 128 bytes of RAM and 16K of ROM. [*] Aside: if sizing is all that important, does that mean you encode the byte size of a struct into its name? I mean, if it's really that important for int to be declared to be a specific size, but you don't similarly mandate the same thing for structs and classes, then this is an academic exercise in pedantry. -- "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> [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| James Kuyper <jameskuyper@verizon.net>: Jun 16 02:59PM -0600 On 06/16/2015 09:05 AM, David Brown wrote: ... > MISRA standards are only £10 or £15 for the pdfs - it's not /that/ > expensive! (But of course any cost makes the whole process a lot more > inconvenient, especially if you just want a quick look for curiosity.) IIRC, the last time I looked it was several hundred US$. A year ago, I would have thought that £10 it would be almost worth paying for, just out of curiosity. However, since the twins arrived I'm paying closer attention to my money. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| "Chris M. Thomasson" <nospam@nospam.nospam>: Jun 16 03:03PM -0600 > concerned the MISRA C++ coding standard for safey critical systems > prohibits the use of basic numerical types and mandates the use of the > typedefs from <cstdint> (or an equivalent). Programming a warplane, anyone?: http://www.stroustrup.com/JSF-AV-rules.pdf ;^) -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 16 04:47PM -0600 On 16/06/2015 21:59, Richard wrote: > simply because that was the default size of an int? Forcing them all > into a 16-bit straight jacket impedes portability instead of enhancing > it. This is why you should design things properly perhaps by the use of a traits class specialized for different hardware which has its own public typedefs: template <typename HardwareType> struct foo_traits; template <> struct foo_traits<ZXSpectrum48K> { typedef uint16_t index_type; }; typedef foo_traits<ZXSpectrum48K>::index_type index_type; /* use index_type rather than uint16_t directly. */ /Flibble -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| David Brown <david.brown@hesbynett.no>: Jun 16 04:47PM -0600 On 16/06/15 22:59, James Kuyper wrote: > would have thought that £10 it would be almost worth paying for, just > out of curiosity. However, since the twins arrived I'm paying closer > attention to my money. That must have been a /long/ time ago - or perhaps you are mixing it with some other standards (such as the current C++ standard, which is an absurd $265). If you have anything specific you want to ask about MISRA, let me know and I can look it up - I can't send you a copy (since it would be copyright infringement, and the pdf is watermarked with my name). -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 16 04:47PM -0600 On 16/06/2015 22:03, Chris M. Thomasson wrote: >> typedefs from <cstdint> (or an equivalent). > Programming a warplane, anyone?: > http://www.stroustrup.com/JSF-AV-rules.pdf From that document (relevant to this thread): AV Rule 209 (MISRA Rule 13, Revised) The basic types of int, short, long, float and double *shall not* be used, but specific-length equivalents should be typedef'd accordingly for each compiler, and these type names used in the code. Rationale: Since the storage length of types can vary from compiler to compiler and platform-to-platform, this rule ensures that code can be easily reconfigured for storage size differences by simply changing definitions in one file. See AV Rule 209 in Appendix A for additional details. Exception: Basic types are permitted in low-level routines to assist in the management of word alignment issues (e.g. memory allocators). MISRA rule was changed from should to shall. /Flibble -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| Doug Mika <dougmmika@gmail.com>: Jun 16 01:52PM -0700 On Tuesday, June 16, 2015 at 1:03:41 PM UTC-5, Richard wrote: > The Computer Graphics Museum <http://computergraphicsmuseum.org> > The Terminals Wiki <http://terminals.classiccmp.org> > Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> My first question was indeed, what is ->, that's clear now. But the question that remains is why would we overload the + operator on a class C, for example, outside of the class? Why not include operator+ inside our class C definition? |
| legalize+jeeves@mail.xmission.com (Richard): Jun 16 09:11PM [Please do not mail me a copy of your followup] Doug Mika <dougmmika@gmail.com> spake the secret code >But the question that remains is why would we overload the + operator on >a class C, for example, outside of the class? Why not include operator+ >inside our class C definition? Prefer small, simple classes over large ones. If you force everything to be a member function, even those functions that aren't *required* to be a member function, then you end up with the rather large bloated class that is std::string. The rule of thumb is: if you can implement something as a free function (i.e. not a member function) using the public interface of a class then prefer that over a member function. This goes hand-in-hand with the advice for namespaces -- the only thing not in a namespace is your implementation of main(). You put the class and its associated free functions all inside a namespace and then they don't get in the way of other free functions for other classes and ADL guarantees that the right operator+ is selected when used with that class. -- "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> |
| Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 05:13PM -0400 On 6/16/2015 4:52 PM, Doug Mika wrote: > [..] the question that remains is why would we overload the + > operator on a class C, for example, outside of the class? Why not include operator+ inside our class C definition? It's a design choice. Two-operand operators are often defined outside of the class to allow conversions to take place on either operand, not just the right-hand one. V -- I do not respond to top-posted replies, please don't ask |
| Doug Mika <dougmmika@gmail.com>: Jun 16 02:17PM -0700 On Tuesday, June 16, 2015 at 4:13:35 PM UTC-5, Victor Bazarov wrote: > V > -- > I do not respond to top-posted replies, please don't ask What sort of conversions are we speaking of? |
| Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 05:22PM -0400 On 6/16/2015 5:17 PM, Doug Mika wrote: >> -- >> I do not respond to top-posted replies, please don't ask > What sort of conversions are we speaking of? <sigh> What book are you reading that doesn't explain conversions? struct ConvertibleFromInt { ConvertibleFromInt(int) {} }; ... ConvertibleFromInt c = 42; Now compare struct PlusAsMember { PlusAsMember(int) {} PlusAsMember operator+(PlusAsMember const& rhs) const; }; ... PlusAsMember p(42); p + 777; // OK 777 + p; // NOT OK with this struct PlusOutside { PlusOutside(int) {} }; PlusOutside operator+(PlusOutside const& o1, PlusOutside const& o2); ... PlusOutside p(42); p + 777; // OK 777 + p; // OK In order to try those things, add code to make them complete programs, then compile. V -- I do not respond to top-posted replies, please don't ask |
| Martin Shobe <martin.shobe@yahoo.com>: Jun 16 02:50PM -0500 On 6/16/2015 2:14 PM, Victor Bazarov wrote: > Allocation of a plain int is often expensive in both memory and time, > and besides, who owns that pointer and who's going to deallocate that > memory when it's not needed anymore? Depends on your design, but the typical case is the caller. > What if a C API call happens > periodically with the same value, do you propose to allocate it every > time and deallocate after the call has returned? Depends on your design, but the typical case is no. > What if API is such > that it needs to retain the value for a few calls? Then it does so. > A literal would be > much less trouble than managing the lifetime of a single 'int'. much less? I think I detect a bit of hyperbole. > Not saying that such a solution is unacceptable, just that it's not > necessarily easy or as clean as it might appear at a first glance. It's not as hard as you are making it out to be. Presumably, the original poster is doing something like this. void bar() { int x = 42; .... // foo will call f with x. foo(f, (void *) x); ... } void f(void * p) { int i = (int) p; ... } The suggested change is to do this instead void bar() { int x = 42; ... // foo will call f with x. foo(f, &x); ... } void f(void * p) { int i = *((int *) p); ... } Martin Shobe |
| Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 03:55PM -0400 On 6/16/2015 3:50 PM, Martin Shobe wrote: >> What if API is such >> that it needs to retain the value for a few calls? > Then it does so. 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... It's an unlikely scenario, yet not completely unheard of, that the API has a state that it wants to maintain. >> A literal would be >> much less trouble than managing the lifetime of a single 'int'. > 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. > int i = *((int *) p); > ... > } Bad idea using C-style casts, that one of the points I failed to deliver, I am guessing... V -- I do not respond to top-posted replies, please don't ask |
| David Brown <david.brown@hesbynett.no>: Jun 16 10:20PM +0200 On 16/06/15 21:50, Martin Shobe wrote: > ... > } > Martin Shobe That's fine as long as x is still alive before f gets called. But often these sorts of things are for registering some sort of callback - foo won't actually call f directly, but arrange for it to be called later. Thus you have to make sure x is still alive after bar has exited - and that means dynamic memory and a lot of pain. A far better arrangement is to use a union instead of a void*, so that you can pass either small value data (such as an int or two) or a pointer to larger data. |
| Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 16 09:37PM +0100 On Tue, 16 Jun 2015 20:16:11 +0200 > Too ,bad ;( > I need intptr_t as conversion is actually passing int parameter as > void* and than back to int. This is a common idiom in C libraries, and if you are doing the conversions that way, and all your numerical manipulation is done using ints, you don't need to worry about whether the size of void* is larger than the size of int. If you begin with a value in the range of int you will end with a value within the range of int and 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.) Chris |
| legalize+jeeves@mail.xmission.com (Richard): Jun 16 09:07PM [Please do not mail me a copy of your followup] Victor Bazarov <v.bazarov@comcast.invalid> spake the secret code >> any void* to a pointer of type T (although the result is undefined >> behavior of the void* didn't come from a pointer to type T). >Allocation of a plain int is often expensive in both memory and time, Code for simplicity, readability and understanding first and get all obsessive about allocating a single int later only if it actually matters. (I'm really hard-pressed to think of a single case where allocating a single int is really going to matter.) >and besides, who owns that pointer and who's going to deallocate that >memory when it's not needed anymore? All these C-style APIs that use void* context pointers have ways of managing the lifetime of the memory. Remember, they already have to solve that problem for C; it is no different for C++. >What if a C API call happens >periodically with the same value, do you propose to allocate it every >time and deallocate after the call has returned? The original poster didn't specify this, but in general, this is NOT how C style callback APIs work when they use a void* context pointer. I've used plenty of them (the X11 Toolkit, Xt, is riddled with them). >Not saying that such a solution is unacceptable, just that it's not >necessarily easy or as clean as it might appear at a first glance. While these concerns aren't unreasonable for some unspecified API, it is not typically how C style APIs with callbacks work. If they are doing any of the things you raise, then their API is simply broken both for C and C++. -- "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> |
| Melzzzzz <mel@zzzzz.com>: Jun 16 11:07PM +0200 On Tue, 16 Jun 2015 22:20:23 +0200 > - foo won't actually call f directly, but arrange for it to be called > later. Thus you have to make sure x is still alive after bar has > exited - and that means dynamic memory and a lot of pain. That is the case. > A far better arrangement is to use a union instead of a void*, so > that you can pass either small value data (such as an int or two) or > a pointer to larger data. Can't change framework. |
| Victor Bazarov <v.bazarov@comcast.invalid>: Jun 16 05:17PM -0400 On 6/16/2015 5:07 PM, Richard wrote: > [..] > The original poster didn't specify this, but in general, this is NOT > how C style callback APIs work when they use a void* context pointer. "All generalizations are wrong". Think about it. > I've used plenty of them (the X11 Toolkit, Xt, is riddled with them). > [..] V -- I do not respond to top-posted replies, please don't ask |
| Noob <root@127.0.0.1>: Jun 16 10:16PM +0200 On 16/06/2015 21:04, Richard wrote: > to the allocator for reuse. All memory obtained from the operating > system (in modern operating systems, anyway) is zeroed before being > given to the allocator in the C++ runtime. I refined the test program. #include <cstring> #include <cstdio> class foo { public: int i = 42; int v[5] = { 1, 2, 3 }; int uninit[100]; }; #define SIZE (1<<16) static void dump(foo *p) { printf("%d %d %d %x\n", p->i, p->v[2], p->v[4], p->uninit[12]); } int main(void) { char *mem = new char[SIZE]; std::memset(mem, 0x1, SIZE); delete[] mem; foo xxa; foo xxb{}; foo *xxc = new foo; foo *xxd = new foo(); foo *xxe = new foo{}; foo *xxf = new foo[20]{}; foo *xxg = new foo[20]; dump(&xxa); dump(&xxb); dump(xxc); dump(xxd); dump(xxe); dump(xxf+3); dump(xxg+7); return 0; } $ g++ -std=c++11 -Wall -Wextra -ggdb3 init.cpp $ ./a.out 42 3 0 f76bbc10 42 3 0 0 42 3 0 1010101 42 3 0 0 42 3 0 0 42 3 0 0 42 3 0 1010101 So the syntax for xxa, xxc, xxg leaves "uninit" uninitialized, while the syntax for xxb, xxd, xxe, xxf 0-initializes "uninit". So if I had a proper C++11 compiler, I could just delete the existing constructors, and change the object definitions to the new foo[N]{}; syntax. What version of Visual C++ fully supports C++11? What version of gcc fully supports C++11? Regards. |
| Noob <root@127.0.0.1>: Jun 16 10:29PM +0200 On 16/06/2015 22:16, Noob wrote: > What version of Visual C++ fully supports C++11? Looking bleak. http://blogs.msdn.com/b/vcblog/archive/2014/11/17/10573602.aspx https://blogs.msdn.com/b/vcblog/archive/2014/08/19/the-future-of-non-static-data-member-initialization.aspx [1] NSDMIs and initializer lists were previously listed as Yes, but have been downgraded to Partial. After users encountered silent bad codegen when using braced-init-lists in NSDMIs and mem-initializer-lists, the compiler team blocked these broken scenarios with a compiler error C2797. This VCBlog post published in August has more info, and this is planned to be completely fixed in 2015 RTM. > What version of gcc fully supports C++11? https://gcc.gnu.org/projects/cxx0x.html Non-static data member initializers supported since gcc 4.7 Regards. |
| legalize+jeeves@mail.xmission.com (Richard): Jun 16 09:02PM [Please do not mail me a copy of your followup] Victor Bazarov <v.bazarov@comcast.invalid> spake the secret code >> What is the difference between new foo; and new foo{}; ? >'new foo' default-initializes the object, 'new foo{}' performs the so >called direct-initialization. They differ a bit. I think they only differ when you actually supply values and not when the list is empty when we're talking about classes. I'm going from 8.5 Initializers in the standard, which says this about direct initialization: "The initialization that occurs in the forms T x(a); T x{a}; as well as in new expressions (5.3.4), static_cast expressions (5.2.9), functional notation type conversions (5.2.3), and base member initializers (12.6.2) is called direct-initialization." I interpret this to mean that the 'a' argument is important here. Earlier it is stated that X a() is value initialization. >The one without the >braces looks for a c-tor that can be called without the arguments, and >if found, calls it. If none exist, it leaves the object uninitialized! Not quite. 8.5 paragraph 12 says "If no initializer is specified for an object, the object is default-initialized." Default initialization is specified as: "To default-initialize an object of type T means: - if T is a class type, the default constructor for T is called (and the initialization is ill-formed if T has no default constructor or overload resolution results in an ambiguity or in a function that is deleted or is inaccessible from the context of the initialization); - if T is an array type, each element is default-initialized; - otherwise, no initialization is performed." I interpret this to mean that the program is ill-formed if the default constructor is unavailable for whatever reason. Generally, ill-formed to a compiler means an error. So when is the "no initialization performed"? If T is anything other than a class, i.e. a scalar type such as int, pointer, double, float, etc. Do you interpret this differently? I am not claiming expertise in the standard, simply interpreting it as I read it. >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. -- "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> |
| 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