Thread: Help understanding how "operator char*()" works.

  1. #16
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    However, I think your point was probably: how do I prevent the silent conversion to 'const char *' from causing problems when used with the subtraction operator. The answer is the same for every operator associated with the intended conversion: provide the operator and either prevent successful compilation or crash with a well-formed error during execution.
    That was kindof the point, wasn't it?
    So, you have an example?
    I'd love to see you thwart the happy little compiler.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #17
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by phantomotap
    The best part of this is: you are both wrong. First, it isn't a counter. Second, even with the implicit conversion it would not compile for a conforming compiler. Subtracting two pointers yields an integer type and 'std::string' has no such constructor.
    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.

    Quote Originally Posted by phantomotap
    However, I think your point was probably: how do I prevent the silent conversion to 'const char *' from causing problems when used with the subtraction operator.
    Precisely, though more generally, "to block otherwise logically illegal, or just silly, operations", as you yourself have pointed out much earlier.

    Quote Originally Posted by phantomotap
    The answer is the same for every operator associated with the intended conversion: provide the operator and either prevent successful compilation or crash with a well-formed error during execution.
    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.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #18
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I'd love to see you thwart the happy little compiler.
    O_o

    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.

    That is easier said than done.
    No. It isn't. I have a series of meta-functions that you simply invoke. (That is, it is as easy done as typed.)

    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.

  4. #19
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by phantomotap View Post
    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.
    In my view, you are opening up evil conversion with the implicit type operator, but then you are blocking them... so you open them up to the compiler and then you block them for the compiler.
    That, essentially means thwart the compiler in my book
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #20
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by phantomotap
    No. It isn't. I have a series of meta-functions that you simply invoke.
    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.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #21
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    In my view, you are opening up evil conversion with the implicit type operator, but then you are blocking them...
    O_o

    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.

    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.
    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.

    Soma
    Last edited by phantomotap; 10-05-2008 at 02:49 AM.

  7. #22
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by phantomotap
    I'm telling the compiler that certain constructs are invalid... I'm basically marking conversions in certain contexts as private.
    Yes, it is like declaring copy constructors and copy assignment operators private in order to disable copying.

    Quote Originally Posted by phantomotap
    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.
    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.

    Quote Originally Posted by phantomotap
    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.
    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.
    Last edited by laserlight; 10-05-2008 at 02:57 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #23
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    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.
    O_o

    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.

  9. #24
    The larch
    Join Date
    May 2006
    Posts
    3,573
    It is interesting that you start by saying
    No. 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++.)
    and you finish with this

    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.)
    So you would prefer:
    Code:
    ofsteam fout(static_cast<const char*>(filename));
    //over
    ofstream fout(filename.c_str());
    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:
    Character c;
    //Rect r = c.bounding_rect();
    Rect r = static_cast<Rect>(c);
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  10. #25
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by phantomotap
    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.
    I do not understand what you are trying to say in the sentence quoted above, so kindly explain and elaborate.

    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.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #26
    Registered User Lawn Gnomusrex's Avatar
    Join Date
    Oct 2008
    Location
    Leading lawn gnomes on the path to world domination! ;o)
    Posts
    13

    Exclamation

    Thank you for explaining
    Code:
    operator char*() {return ptr;}
    I also see this set off a discussion that would have made my head explode if I tried to understand most of it.
    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.)

  12. #27
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The idea is that you create a function such as:
    const char* get();
    In your class instead of the implicit conversion operator:
    operator const char* ();
    This will eliminate the chance for these headaches.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #28
    Registered User Lawn Gnomusrex's Avatar
    Join Date
    Oct 2008
    Location
    Leading lawn gnomes on the path to world domination! ;o)
    Posts
    13
    Ahhh! Thank you, Elysia! I didn't know if making something like this required more work or not.

    I appreciate the help, everyone! Thanks!

  14. #29
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can anybody show me why this works??
    By tzuch in forum C Programming
    Replies: 2
    Last Post: 03-29-2008, 09:03 AM
  2. Understanding formulas, shapes, algorithms etc
    By hardi in forum A Brief History of Cprogramming.com
    Replies: 26
    Last Post: 04-16-2007, 01:23 PM
  3. Works outside of the loop, not within
    By Decrypt in forum C++ Programming
    Replies: 5
    Last Post: 08-05-2006, 12:22 AM
  4. understanding recursive functions
    By houler in forum C Programming
    Replies: 7
    Last Post: 12-09-2004, 12:56 PM
  5. Understanding Headers and Inclusions
    By jdm in forum C++ Programming
    Replies: 11
    Last Post: 04-21-2004, 10:11 PM

Tags for this Thread