Prev: Lifetime of a temporary bound to a reference
Next: When I convert "0.0003" and "3.e-4" in VC++ they are the same
From: Alf P. Steinbach /Usenet on 4 Jul 2010 05:50 * Mathias Gaunard, on 04.07.2010 10:45: > On Jul 2, 9:56 pm, "Alf P. Steinbach /Usenet"<alf.p.steinbach > +use...(a)gmail.com> wrote: >> * Mathias Gaunard, on 01.07.2010 16:23: > >> Depends. In ordinary code, if ADL selects something that is unacceptable then >> that is most probably a design problem that should be fixed. IMHO. >> >> But in Boost-like code and other TMP code that routinely exploits the most >> subtle and intricate features of C++ it may perhaps be extremely dangerous to >> let anything be implicit except where the implicit selection is the point. > > Not only are namespaces in which the argument is in considered by ADL, > the namespace of the template parameters of the arguments are > considered as well. That appears to be the case. E.g. <code> #include <stddef.h> namespace oh { struct Blah {}; template< class Type > inline Type* begin( Type* a ) { return a; } template< class Type > inline void begin( Type& a ) {} } namespace my { template< class Type > struct Array { Type* begin() { return 0; } }; //template< class Type > //inline Type* begin( Array< Type >& a ) { return a.begin(); } } int main() { using namespace my; Array< oh::Blah > a; begin( a ); } </code> compiles nicely with g++, msvc and comeau online. > This means that something like > boost::array<boost::fusion<int, char>, 42> array; > begin(array); I think you mean boost::fusion::tuple? > is ambiguous, as both boost::begin and boost::fusion::begin are being > considered. Removing the comment in the above code example, whence it *still* compiles nicely, shows that ordinary code generally works OK even with such subtleties involved, and even with general function templates involved. The specificity rules take care of it. I think that /both/ Boost and the Holy Standard should be fixed. Boost should be fixed to work with 'using' and the current standard. And re the standard: when you have to travel to the North pole to get your food coupon which you can exchange for food in a store in Hong Kong, if they currently have any food from Ching Chong, well then you know that those guys designing the rules are just having you on. They've designed some ridicilously overcomplicated thing that conforms to nonsense rules such as rhyming, and have managed to convince you that in spite of the extraordinary ridiculousness & impracticalness it's meaningful in some /deep/ way -- bah! So, also the HS should IMO be fixed to remove that ADL lookup that nobody will ever mean to invoke. In the meantime, I don't think it matters much for ordinary code. Like above. Cheers, - Alf -- blog at <url: http://alfps.wordpress.com> [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Walter Bright on 5 Jul 2010 02:11 {To correct the funky line endings, format posts with a line length of 70 --mod} nmm1(a)cam.ac.uk wrote: > A simpler and safer rule is never to use unsigned, but that isn't > feasible in C and C++. I still think unsigneds are appropriate when used for bit masks and manual bit fields. They're also correct for working with UTF-8 and UTF-16, etc. One of the more annoying historical artifacts of C and C++ is the "randomly" signed nature of the char type. You have to use it because strings are based on the char type, not explicitly signed or unsigned char, and there's no way to check for latent bugs in your code that will only surface if the sign of char randomly changes. (Yes, I meant randomly signed instead of implementation-defined signed, because nothing says that the signedness cannot change from compiler to compiler, or compiler version to compiler version, or even based on compiler switch settings.) The C and C++ standards should really make char types unsigned, and drive a stake through the heart of trigraphs. If exported templates could be set adrift on an ice floe, perhaps there is hope! -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Leigh Johnston on 5 Jul 2010 10:48 "Walter Bright" <newshound1(a)digitalmars.com> wrote in message news:i0qldf$tdr$1(a)news.eternal-september.org... > {To correct the funky line endings, format posts with a line length of > 70 --mod} > > nmm1(a)cam.ac.uk wrote: >> A simpler and safer rule is never to use unsigned, but that isn't >> feasible in C and C++. > > I still think unsigneds are appropriate when used for bit masks and manual > bit > fields. They're also correct for working with UTF-8 and UTF-16, etc. > The main reason cited for not using unsigned integral types is the potential for bug creation when mixing signed and unsigned integral types in an expression. This reason is invalid because there is the potential for bug creation using *any* language feature. Using unsigned integral types to represent values which are only ever positive or zero is perfectly fine. It is impossible to avoid interfacing with unsigned integral types when using the C++ and C standard libraries further invalidating the often cited reason given above. /Leigh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mathias Gaunard on 5 Jul 2010 10:45 On Jul 4, 9:50 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach +use...(a)gmail.com> wrote: > Removing the comment in the above code example, whence it *still* compiles nicely, shows that ordinary code generally works OK > even with such subtleties involved, and even with general function templates involved. > namespace my { > template< class Type > > struct Array { Type* begin() { return 0; } }; > > //template< class Type > > //inline Type* begin( Array< Type >& a ) { return a.begin(); } If you write that as template< class Type > inline Type* begin( Type& a ) { return a.begin(); } Which is common enough in ordinary code (because people don't like preventing implicit conversions to happen), then it's ambiguous. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Seungbeom Kim on 5 Jul 2010 21:46
On 2010-07-04 13:47, Alf P. Steinbach /Usenet wrote: > * Jens Schmidt, on 04.07.2010 10:46: >> For countdown: why not just use a pattern like >> for_down (Index i = size (v); i> 0; --i)? >> >> Here for(a;b;c) d; expands as usual to >> >> a; while (b) { d; c; } >> >> and for_down(a;b;c) d; expands to >> >> a; while (b) { c; d; } >> >> (note the reversed order in the body). This pattern works with >> signed and unsigned types. > > Well, extending the language with a 'for_down' construct isn't necessary. It isn't strictly necessary; we could even live without 'for' and use 'while' exclusively, anyway. But the omission of such a separate construct does give a disadvantage to backward iteration. See below. > The ordinary 'for' works OK for countdown with signed counter variable, > and can with some effort be pressed into service also for unsigned > counter variable. It's one of the problems with unsigned variables. It's > not a significant problem with the 'for' loop itself, since the loop > contstruct can be applied e.g. with signed variable. It's not just a problem between signed and unsigned integers, but applies equally to pointers and iterators, which cannot advance beyond the 'begin' and the 'end' values. Unsigned integers are just a special case of this where the 'begin' value is 0. The design of the 'for' statement is, as I understand it, influenced by and favorable to the convention of iterating forward over the range [begin, end). Without 'for', one would naturally write: i = begin; while (i != end) { // use i i++; } which is quite compatible with the post-increment operator and the current design of the 'for' statement. On the other hand, if you want to iterate backward over the same range, the canonical way would be: i = end; while (i != begin) { --i; // use i } Note the pre-decrement. This is perfectly symmetrical to the forward iteration case, and there's nothing wrong with a separate 'for_down' statement (apart from its spelling, maybe) that directly supports this convention: for_down (i = end; i != begin; --i) { // use i } but this kind of iteration was not very common and just didn't make it to the invention. This can also be done with the current 'for' statement, but it's just more clumsy: for (i = end; i != begin; /* empty */) { --i; // use i } So, it's not just the problem of signed vs unsigned integers, and the problem is not in unsigned integers, but the "compatibility" or the "match": it's just that the current for loop is made more favorable to forward iteration, and that backward iteration is not supported by a corresponding separate statement. > Regarding 'for' loops what we need is, IMHO, a 'for_each'. The standard > library's 'for_each' just doesn't cut it, in any way. Happily C++0x > �6.5.4 defines such a loop, unfortunately called 'for' like the old one, > but. Why do you think it is unfortunate? Do you want another keyword? -- Seungbeom Kim [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |