I do not see what "it isn't a counter" has to do with anything. Concerning the error: I ignored that part due to the disclaimer that only C++ Coding Standards incorporates corrections, but thinking about it further, it cuts both ways: suppose the constructor that creates a string with n characters was changed such that the null character was default. In that case, implicit conversion would allow Sutter's otherwise problematic original example to compile when the conversion function is provided.Originally Posted by phantomotap
Precisely, though more generally, "to block otherwise logically illegal, or just silly, operations", as you yourself have pointed out much earlier.Originally Posted by phantomotap
That is easier said than done. Providing a named conversion function, on the other hand, is as easily done as said, and avoids those problems associated with implicit conversions.Originally Posted by phantomotap
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
O_oI'd love to see you thwart the happy little compiler.
Thwart the compiler?! Are you insane?! I'm suggesting you use the compiler. That's why it exists. What don't you get? You can literally use any method of static assertion or compiler firewall you desire.
As I've implied: I use a meta-function to do this for any or all of the operators applied to any number of types--actually limited to 64. The massive overhead would be pointless, but I'll offer a trivial and sloppy way to block an operator for a type you don't own without otherwise affecting the compiler output, messages or errors, from "correct" source. Enjoy.
No. It isn't. I have a series of meta-functions that you simply invoke. (That is, it is as easy done as typed.)That is easier said than done.
Soma
Code:class blocker{public: blocker(){} private:blocker(const blocker &){} friend blocker operator - (const my_string &, const my_string &);}; blocker operator - ( const my_string & lhs, const my_string & rhs ) { blocker return_value; return(return_value); }
Last edited by phantomotap; 10-05-2008 at 02:19 AM.
You still have to determine what to invoke, and have to update your code if there are additions to the target type interface (for class types not under your control, at least), even if these would not normally affect your code.Originally Posted by phantomotap
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
O_oIn my view, you are opening up evil conversion with the implicit type operator, but then you are blocking them...
Yea... that would be silly, but I'm not blocking the conversion. I'm telling the compiler that certain constructs are invalid... I'm basically marking conversions in certain contexts as private.
If your code would not be affected by such additions then, by definition, no source change would be needed regardless of the source written to prevent such constructs from compiling. (Edit: Actually, I may be giving to much credit here; it is possible to write source that depends upon the firewall for correct compilation, but it is very unlikely to happen by accident.) That said, if you desire that your source makes use of these additional facilities, you would have to change something, but that's always the case.You still have to determine what to invoke, and have to update your code if there are additions to the target type interface (for class types not control your control, at least), even if these would not normally affect your code.
Soma
Last edited by phantomotap; 10-05-2008 at 02:49 AM.
Yes, it is like declaring copy constructors and copy assignment operators private in order to disable copying.Originally Posted by phantomotap
Ah, but what if the type you are designing is intended for use (or just might be used) by another programmer (or team, as the case may be), as would be the case for a library? Such a source code change would be needed in order to maintain the interface provided.Originally Posted by phantomotap
When you put it as "additional facilities", I tend to agree with the notion that this would be a viable alternative to a named conversion function, though I am not convinced that it is worth the effort when a named conversion function can be clearer and just shifts the burden on using sensible operations from other types to the user of the type you provide.Originally Posted by phantomotap
Last edited by laserlight; 10-05-2008 at 02:57 AM.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
O_oWhen you put it as "additional facilities", I tend to agree with the notion that this would be a viable alternative to a named conversion function, though I am not convinced that it is worth the effort when a named conversion function can be clearer and just shifts the burden on using sensible operations from other types to the user of the type you provide.
I think I've spotted a flaw in your understanding. In a perfect world the responsibility, or burden if you like, of disabling conversions for specific constructs belongs to the provider of a type. (You wouldn't, or shouldn't, in using my library, or any other, go into the headers to mark some method private even if it should have been marked private.) Even in our world of shambles, the responsibility belongs to a single type. (Granted, in this case I've offered that it can "fix" an existing provision that didn't account for unwanted implicit conversion by displacing this burden, but that's not really the point.) The relevant source, even without templates, need only be written to disallow problematic conversions for each implicitly converted type for any given class type with such implicit conversions. The 'blocking' type is a "no-op"; it is no more associated with the relevant type nor any more responsible than 'std::string' would be if someone provides 'std::string operator + (const std::vector<?> &, unsigned long)'.
Soma
PS. And not that it matters, but I'm a big fan of consistency. I teach people to use 'static_cast<?>' even with classes offering implicit conversion. (With an exception of 'operator void *' and 'operator bool' because stream using source seems "right" without it.)
Last edited by phantomotap; 10-05-2008 at 04:24 AM.
It is interesting that you start by saying
and you finish with thisNo. They should not be avoided. If you do the work to block otherwise logically illegal, or just silly, operations they can make code much cleaner. (Of course, misused they can make code uglier, but that doesn't say much as it applies to most features of C++.)
So you would prefer:PS. And not that it matters, but I'm a big fan of consistency. I teach people to use 'static_cast<?>' even with classes offering implicit conversion. (With an exception of 'operator void *' and 'operator bool' because stream using source seems "right" without it.)
Does this apply only to string-like things? Many classes can return objects of various types from different methods, would you also make the classes castable into these types?Code:ofsteam fout(static_cast<const char*>(filename)); //over ofstream fout(filename.c_str());
Code:Character c; //Rect r = c.bounding_rect(); Rect r = static_cast<Rect>(c);
I might be wrong.
Quoted more than 1000 times (I hope).Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
I do not understand what you are trying to say in the sentence quoted above, so kindly explain and elaborate.Originally Posted by phantomotap
What I meant is that since a named conversion function forces the user of the type to explicitly request the conversion, any abuse of this conversion is the user's fault. With an implicit conversion function, any abuse of this conversion is both the user's fault and the type designer's (or implementor's) fault. The former is at fault for a mistake in using the type, and the latter is at fault for failing to disable the constructs that are not sensible.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
Thank you for explaining
I also see this set off a discussion that would have made my head explode if I tried to understand most of it.Code:operator char*() {return ptr;}
I guess the point of this 'don't use automatic conversions'? I understood only the a = b - c issue, I don't know how widgets work, so I didn't understand it.
I've never touched any programming language before, so my total programming experience extends to about 5 months. ^^;
I'm reading "C++ without fear", if that indicates how new I am to all of this. So I don't really know how to make an explicit conversion function. I saw this in the "books" sections of cprogramming, so I'm reading those. I looked into other books, but I know so little I didn't know what to go with. So this is the first book I ended up getting.
I got the information I came for though, So thanks everyone! (And when I figure out how to write a function to take the place of operator char*(), I'll be sure to use it.)
Ahhh! Thank you, Elysia! I didn't know if making something like this required more work or not.
I appreciate the help, everyone! Thanks!
Also, non-const char* is bad for encapsulation. Basically, by returning a non-const char*, you implicitly give clients of your class leave to do with your internal string data whatever they want - not a good idea when the char* really belongs to the string object.
All the buzzt!
CornedBee
"There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
- Flon's Law