Thread: Conversion to bool screwing up my + overloading

  1. #16
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> t += 10.0;

    The implicit boolean conversion returns an rvalue, so that wouldn't be a problem.

    >> int* p = NULL;
    >> p = p + a;

    A double doesn't implicitly convert to an int, so no go there, either.

    Mind you, there may be situations where you want to prevent even the most unlikely conversions, and in those cases you could use something more robust, such as the "safe bool idiom". But for many classes, a simple double_hack (or similar) will suffice, eg: adding numbers to the object and other such operations don't even make sense in the context of the class, so why bother?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #17
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It's difficult to know exactly what is lvalue vs rvalue.
    But still, I'd go with something similar to the safe bool idom. Return a class member pointer, because it isn't implicitly convertible to anything else.
    There's also the void* operator.
    And then there's the question of disallow nonsensical operations.
    I could do...
    Code:
    test t;
    if (t == 10)
    ...which makes no sense.
    I suppose your double solution is okay, but I'd go a step further.
    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.

  3. #18
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> There's also the void* operator.

    Hey, that looks like a better solution altogether, actually.

    I'm wondering if it provides all the safety of the standard "safe bool idiom" while being quite efficient as well?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #19
    The larch
    Join Date
    May 2006
    Posts
    3,573
    That's what standard streams use. You can do things like:

    Code:
    const char* s = "Hello";
    std::cout < s; //may not compile on all compilers
    
    std::cout << std::cin; //outputs the address of std::cin
    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).

  5. #20
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    void* does allow for some nonsensical stuff, as well. The Safe Bool Idom article does describe the approach.
    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.

  6. #21
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> void* does allow for some nonsensical stuff, as well. The Safe Bool Idom article does describe the approach.

    I don't know. The Safe Bool Idom is a very heavy-handed solution, and I just don't see the point in going so far to prevent clearly dubious usage. You have to draw the line somewhere.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  7. #22
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Which is why they offer a generic, re-usable solution at the end.
    You simply implement a member function that does the boolean operation and inherit from the safe bool class and you're done.
    Not that I've gotten it to work, but that's another matter.
    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.

  8. #23
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    What about this? It's pretty lightweight, and it should work just fine:

    Code:
    namespace detail_ {
    
    struct implicit_bool
    {
    	void implicit_true( void )
    	{	}
    	
    	private:
    	
    	implicit_bool( void );
    };
    
    }
    
    typedef void ( detail_::implicit_bool::* implicit_bool )( void );
    	
    implicit_bool const
    	implicit_true = &detail_::implicit_bool::implicit_true, 
    	implicit_false = 0;
    
    struct test
    {
    	test( void )
    	{	}
    	
    	test( char const* )
    	{	}
    		
    	operator implicit_bool( void )
    	{		
    		return implicit_true;
    	}
    	
    	friend test operator + ( test const&, test const& )
    	{	
    		return test( );
    	}
    };
    
    int main( void )
    {
    	test
    		a, 
    		b = a + "foo";
    	if( b )
    	{
    		
    	}
    }
    Last edited by Sebastiani; 06-24-2009 at 05:44 AM. Reason: const correctness added
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #24
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Something like that, yeah.
    What the safe bool idom does differently, I believe, is the naming scheme in order to give hints as to why a compile error occurs, for example, if the object does not support boolean testing (but then again, why would you need that?).
    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.

  10. #25
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Sebastiani
    What about this? It's pretty lightweight, and it should work just fine:
    I suppose that you would declare implicit_true and implicit_false as extern const, then also disable comparison operators by default. As for lightweight: it seems about as "heavy handed" as the safe bool idiom.

    In my opinion, the real fix would come with explicit conversion functions in C++0x.
    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
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    The only drawback, really, is having to use the implicit_true/implicit_false objects explicitly, eg: you obviously couldn't simply return true from the function (although false would work).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  12. #27
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> I suppose that you would declare implicit_true and implicit_false as extern const, then also disable comparison operators by default.

    Yes, that would be a good idea, wouldn't it?

    >> In my opinion, the real fix would come with explicit conversion functions in C++0x.

    Absolutely. It's a shame we have to come up with silly hacks like this, really.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #28
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by laserlight View Post
    In my opinion, the real fix would come with explicit conversion functions in C++0x.
    I'll agree to that.
    It's been one of the most promising features 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.

  14. #29
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    What's so heavy-handed about safe_bool?
    Code:
    class with_conversion
    {
      void fn() {};
      typedef void (with_conversion::*safe_bool)();
    
    public:
      operator safe_bool() {
        return am_i_true() ? &with_conversion::fn : 0;
      }
    };
    It's five lines in its simple form. You can even reuse an existing member function if you feel like saving one line. True, if you go the full length to get somewhat good error messages and avoid abuse it becomes longer, but that's what the generic utility is for.

    Of course, this is much nicer, as I think everyone can agree:
    Code:
    class with_conversion
    {
    public:
      explicit operator bool() {
        return am_i_true();
      }
    };
    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

  15. #30
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by Elysia View Post
    It's difficult to know exactly what is lvalue vs rvalue.
    What are Lvalues and Rvalues?

    Now you know!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  2. Smart pointer class
    By Elysia in forum C++ Programming
    Replies: 63
    Last Post: 11-03-2007, 07:05 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. Headers that use each other
    By nickname_changed in forum C++ Programming
    Replies: 7
    Last Post: 10-03-2003, 04:25 AM