Thread: Conversion to bool screwing up my + overloading

  1. #1
    Registered User Sharke's Avatar
    Join Date
    Jun 2008
    Location
    NYC
    Posts
    303

    Conversion to bool screwing up my + overloading

    I'm still screwing on with a simplified string class, "Str,"which originated from a chapter of "Accelerated C++" and which I'm adding to for exercise questions (and my own amusement). Here is the problem: I have a constructor which converts a const char to a Str. The + operator is overloaded for Str. Therefore I can add a const char to a Str. It broke as soon as I added a conversion to bool for the purposes of using a Str as a condition. Now, I can't add a const char to a Str because the compiler complains thus (I'm paraphrasing):

    error C2666: 'operator +' : 2 overloads have similar conversions
    could be 'Str operator +(const Str &,const Str &)'
    1> or 'built-in C++ operator+(int, const char [6])'
    So it seems that since I now have a conversion from Str to Bool, there's an ambiguity because the compiler could theoretically pass the bool as an int to the 2nd overload. I was for some unknown reason under the impression that C++ didn't convert from bool to int, but there it is anyway. My question is, what can I do to fix it?

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Yep, it's just one of those annoyances of the language. The only way I could think to do this would be a bit of a hack:

    Code:
    struct test
    {
    	protected:
    	
    	typedef double
    		boolean_hack;
    
    	public:	
    		
    	test( void )
    	{	}
    	
    	test( char const* )
    	{	}
    		
    	operator boolean_hack( void )
    	{	
    		return true;
    	}
    	
    	friend test operator + ( test const&, test const& )
    	{	
    		return test( );
    	}
    };
    
    int main( void )
    {
    	test
    		a, 
    		b = a + "foo";
    	if( b )
    	{
    	
    	}
    }
    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;
    }

  3. #3
    Registered User Sharke's Avatar
    Join Date
    Jun 2008
    Location
    NYC
    Posts
    303
    Horrible! But works perfectly! Thanks.

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    The Safe Bool Idiom

    Conversion operators in general create all sorts of problems. They allow expressions to be valid which you never intended to be valid, and can produce ambiguities which make it impossible to compile certain expressions which appear valid.

    I don't use the Safe Bool idiom myself. It forces me to do something far too bizarre to support a conversion that adds only a little bit of syntactic convenience. Instead I just provide a single IsNull() member function.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> The Safe Bool Idiom

    It seems sort of over-the-top to me, but it is pretty clever, anyway.

    >> I don't use the Safe Bool idiom myself. It forces me to do something far too bizarre to support a conversion that adds only a little bit of syntactic convenience. Instead I just provide a single IsNull() member function.

    I agree, although I would prefer a function named 'empty', or similar.
    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;
    }

  6. #6
    the hat of redundancy hat nvoigt's Avatar
    Join Date
    Aug 2001
    Location
    Hannover, Germany
    Posts
    3,130
    Quote Originally Posted by Sebastiani View Post
    I agree, although I would prefer a function named 'empty', or similar.
    Please name it something_similar() or maybe even is_empty() The use of a word that could be a verb or an adjective is sooo frustrating when you don't have memorized each function in the language you are currently programming in. Every time I switch back to C++ I try to wrap my head around the fact that "empty" will not empty my string.
    hth
    -nv

    She was so Blonde, she spent 20 minutes looking at the orange juice can because it said "Concentrate."

    When in doubt, read the FAQ.
    Then ask a smart question.

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It seems sort of over-the-top to me, but it is pretty clever, anyway.
    It's not over-the-top. It's exactly what is needed to support the implicit use in conditions without creating loads of problems. Anything less causes problems without end.
    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
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Every time I switch back to C++ I try to wrap my head around the fact that "empty" will not empty my string.

    Ha! Yes, that's quite understandable.
    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. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> It's not over-the-top. It's exactly what is needed to support the implicit use in conditions without creating loads of problems. Anything less causes problems without end.

    Can you give an example of how the code I posted could create any problems?
    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;
    }

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I have looked into using the safe bool idiom on occasion, but I found that all I really needed was operator !
    I would still consider using it in future.

  11. #11
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> I have looked into using the safe bool idiom on occasion, but I found that all I really needed was operator ! I would still consider using it in future.

    The only thing about that is the akward !!x syntax. But yeah, at least it's unambiguous, and easy to type.
    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. #12
    The larch
    Join Date
    May 2006
    Posts
    3,573
    If I'm not mistaken C++0x adds explicit conversion operators which makes conversions to bool work correctly (happen implicitly only in boolean expressions).
    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).

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Sebastiani View Post
    >> It's not over-the-top. It's exactly what is needed to support the implicit use in conditions without creating loads of problems. Anything less causes problems without end.

    Can you give an example of how the code I posted could create any problems?
    Hmm...
    Code:
    int main()
    {
        test a;
        double d = a + 10;
    }
    I believe this will cause a nasty implicit conversion.
    I don't know if you can add a double to a pointer, but if you can, you can do...
    Code:
    int* p = NULL;
    p = p + a;
    ...too. Nasty.

    Quote Originally Posted by anon View Post
    If I'm not mistaken C++0x adds explicit conversion operators which makes conversions to bool work correctly (happen implicitly only in boolean expressions).
    It does (add explicit conversion operators), but now the question is if any compiler has implemented it yet.
    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. #14
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> double d = a + 10;

    Well, sure, but that isn't a very plausible situation either.
    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;
    }

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    How about...
    Code:
    test t;
    t += 10.0;
    It might just work and will be a glaring bug, not doing what you expect it to.
    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.

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