Thread: Overload the..bool operator..?

  1. #1
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217

    Overload the..bool operator..?

    I want to use a class like this:

    Code:
    Item item;
    
    if(item)
    {
    ....
    }
    Instead of this:

    Code:
    Item item;
    
    if(item.IsValid())
    {
    ...
    }
    Is there a way to do this? Maybe overload an operator?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Read about the safe bool idiom. Besides learning about the idiom itself, take note of the author's words towards the end about when not to use it.
    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. #3
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    Thank you.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Ah, it makes me shift in my chair everytime I read about what nonsense those conversion operators can achieve... every single time.
    Thank goodness for explicit conversion operators in C++0x.
    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. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    If the Item was "invalid" in the first place, why was it allowed to be constructed? Maybe you should throw an exception when the item would be constructed in an invalid state, so that users don't have to perpetually wonder whether the objects they possess are valid or junk.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Read about the safe bool idiom.
    O_o

    ^_^

    Thank goodness for explicit conversion operators in C++0x.
    It only disallows an additional conversion in a given context. It will help, and no doubt, but it doesn't solve all the problems.

    Soma

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    If it doesn't solve all the technical problems, please tell me which it doesn't solve. It was designed primarily because of this very use case, and if it doesn't solve all problems, it's broken and needs to be revised.
    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

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Does it solve the problem that things like x < y might compile because of operator bool (there isn't any other implicit casts)?
    Or that you might accidentally pass the object to a function that accepts it because it expects bool?
    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).

  9. #9
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    Quote Originally Posted by brewbuck View Post
    If the Item was "invalid" in the first place, why was it allowed to be constructed? Maybe you should throw an exception when the item would be constructed in an invalid state, so that users don't have to perpetually wonder whether the objects they possess are valid or junk.
    Well it's part of their inventory:

    Code:
    class Player:
      public Character
    {
    private:
    ...
    Item items[9];
    ...
    };
    Item is a very basic class which pretty much looks like this:

    Code:
    class Item
    {
    private:
        const ItemClass* itemClass;
        int level;
    
    public:
        Item(const ItemClass* itemClass, int level) {
            this->itemClass = itemClass;
            this->level = level;
        }
    ....
    }
    Where ItemClass* contains the behaviour and appearance loaded from an XML file. The player might not have any item in that position at all.

    I suppose i could of done it like this and check if item is NULL:
    Code:
    class Player:
      public Character
    {
    private:
    ...
    Item* items[9];
    ...
    };
    ...but then again i could do it the way i have it now.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by 39ster View Post
    Well it's part of their inventory:

    Code:
    class Player:
      public Character
    {
    private:
    ...
    Item items[9];
    ...
    };
    I think it just boils down to not using the right data structure. It seems like a vector might be more suited to this task than a fixed-size array. Then when an item goes away you could just erase() it from the vector. Unless for some reason you need to have the same item always be at the same index (the player refers to them by number of something)?

    At any rate what I'm seeing here is a design choice in one part of the program leaking into another part which places weird requirements on the Item class
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  11. #11
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    If i use a vector or list it's going to screw up the item placement. I want them to be able to choose which position to put the item. They can place the item in the 8th position even if they only have one item, so it needs to support gaps in between items.

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by 39ster View Post
    If i use a vector or list it's going to screw up the item placement. I want them to be able to choose which position to put the item. They can place the item in the 8th position even if they only have one item, so it needs to support gaps in between items.
    I can see how doing what you're doing now makes that simpler, but I still would recommend some other approach than providing some kind of validity check for the items. If an item can be invalid, then any code which accesses that item either has to assume its valid, or remember to check for validity before using it.

    What if your inventory was a std::map<int, Item>, then the syntax is mostly the same but you don't have to keep track of which indices actually refer to valid items.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    Yeah i was just thinking about using a map.

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by anon
    Does it solve the problem that things like x < y might compile because of operator bool (there isn't any other implicit casts)?
    Or that you might accidentally pass the object to a function that accepts it because it expects bool?
    Reading the N2437 working paper, I would say yes. You can do neither since there must be an explicit cast of some sort. On the other hand, the Wikipedia C++0x article gives the impression that explicit conversion functions only prevent implicit secondary conversions, so I guess that phantomotap either only read the Wikipedia article, or interpreted the N2437 working paper differently (but the examples seem pretty clear to me).

    Quote Originally Posted by 39ster
    Yeah i was just thinking about using a map.
    Yes, that seems like the best fit for your problem at the moment.
    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

  15. #15
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    It was designed primarily [...] needs to be revised.
    Uh... conversion operators already existed. The addition of explicit conversion operators can't have been offered to provide for this use case since you could already do that.

    Anyway, I seriously don't quite get what you are suggesting or asking. The explicit conversion operators naturally disallows this use case and any others similar to it.

    If it doesn't solve all the technical problems, please tell me which it doesn't solve.
    The ideal implicit conversion: conversion in the face of source strongly implying that the conversion should take place while disallowing conversions in the ambiguous or dangerous case. The addition and use of explicit conversion operators effectively denies that possibility entirely. (Of course, that was the intended purpose, and as far as it goes, it works.) They do so precisely because they require explicit source.

    Seriously, the addition of the explicit conversion operators effectively renames the normally offered "best practice" of 'bool some_type::is_valid()' in use from 'some_type_instance.is_valid()' to 'static_cast<bool>(some_type_instance)' or 'bool(some_type_instance)'. Now, granted, this isn't the only application, and it does solve, after a fashion, the problem of what to name a given conversion function. In this the implicit conversion operators are beautiful and a nice blessing, but only if you can actually get old hats and newbies to use them as intended.

    But can you overload the given explicit conversion operator for your ranged integer class and rely on the existing, natural operators to work while still prevent the bothersome implied conversion in other constructs? No.

    Does it solve the problem that things like x < y might compile because of operator bool?
    Absolutely. (Not that you couldn't already do that, but this certainly makes it simpler which is always nice.)

    Or that you might accidentally pass the object to a function that accepts it because it expects bool?
    Absolutely.

    On the other hand, the [...] the N2437 working paper differently.
    O_o

    I intended to imply "disallow an additional conversion possibility separate from other implicit conversions in a given context". (Consider what happens when the explicit form from one type gets cozy with a non-explicit conversion from the other.) I'm not sure what you inferred but I think it was the wrong thing. *shrug*

    Anyway, they, the examples, look absolutely transparent to me as well; nearly there is also the "inheritance" from the current standard of the given definition for 'class X' in those same examples.

    The point is, for this exact use case, users will still have to deal with implicit conversion operators because they, the explicit conversion operators, don't really solve many problems. They just make the problems appear to vanish because they require the programmer to tell the compiler exactly what to do. If I don't mind doing 'if(bool(some_instance))' the explicit operators are fine, but if I need 'if(some_instance)' I still have to do the work because I can't use the explicit operators. (I chose this example because it was what the OP asked. This is really one of the least useful and least obtrusive cases.)

    I actually don't mind 'static_cast<bool>(instance)'. No, that's not quite all of it; I prefer 'static_cast<bool>(instance)'. I like unambiguous statements. I also like the constructor form of assignment. (I use 'type name(arg);' instead of 'type name = arg;'.) The thing is... most programmers will not have it. We can't even get Elysia to use the C++ casts!

    Soma

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. passing params between managed c++ and unmanaged c++
    By cechen in forum C++ Programming
    Replies: 11
    Last Post: 02-03-2009, 08:46 AM
  2. Drawing Program
    By Max_Payne in forum C++ Programming
    Replies: 21
    Last Post: 12-21-2007, 05:34 PM
  3. Smart pointer class
    By Elysia in forum C++ Programming
    Replies: 63
    Last Post: 11-03-2007, 07:05 AM
  4. operator overloading and dynamic memory program
    By jlmac2001 in forum C++ Programming
    Replies: 3
    Last Post: 04-06-2003, 11:51 PM
  5. Need Help With an RPG Style Game
    By JayDog in forum Game Programming
    Replies: 6
    Last Post: 03-30-2003, 08:43 PM