Thread: Forcing an enum to int?

  1. #1
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Forcing an enum to int?

    Code:
    class Object {
    public:
    
     enum STYLE { SOLID = 0, NUL, HATCHED, PATTERN };
     enum HATCH { HORIZONTAL = 0, VERTICAL, FDIAGONAL, BDIAGONAL, CROSS, DIAGCROSS };
    
    bool MakeHatched( HATCH style ) {
      //...
     }
    };
    
    
    int main() {
      Object b;
    
       //...OK...
      b.MakeHatched( Object::VERTICAL ); 
      
       //...nope, compiler rejects, needs a HATCH, cool...
      b.MakeHatched(Object::SOLID); 
     
    
     //... no matching call to MakeHatched(int);  
     //...canidates are MakeHatched(HATCH);  
      b.MakeHatched( 1 ); //...damn. I want to be able to use an int!
       
     }
    So is there any way to force it to accept both? Because when I make a wrapper for the int, it accepts this:


    Code:
       //...This compiles! No good!! Must be a HATCH!
      b.MakeHatched(Object::SOLID);
    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. #2
    Evil Member
    Join Date
    Jan 2002
    Posts
    638

    Well...

    You can't implicitly convert an int to an enum, because your integer value 1 is not of type Object::HATCH.

    You could do this...

    Code:
    b.MakeHatched(Object::HATCH(1));

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I was afraid of that! Ok, so no workarounds, huh? Thought maybe there was an undocumented feature of the enum I could exploit
    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. #4
    Evil Member
    Join Date
    Jan 2002
    Posts
    638
    Well, because most int values are out of the range of a reasonable enum, there is no implicit conversion between them.

    However...

    You might could do somehting EVIL though...

    If you want to only use ints....

    Prelude, Salem, shield your eyes...

    You might not want to see this...

    Between your class and your code...

    Code:
    #define MakeHatched(X) \
            MakeHatched(Object::HATCH(X))

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    You son of a ***, it almost worked too! Hacker!

    Unfortunately, it still allows:

    b.MakeHatched(10000);

    Nice try though! Kudos....
    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
    Evil Member
    Join Date
    Jan 2002
    Posts
    638
    That is WHY there is no implicit conversion from an int to an enum.

    The behaviour of an enum getting assigned to an out of range value would be undefined. The same thing would happen if you just used Object::HATCH(10000)

    By hacking your way around that you open yourself to this type of undefined situation.

    You could invent a definition, if you wanted to, such as either modulo'ing it against the maximum number of values of hatch, or even throwing an exception if it was an out of range value.

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Yeah, that's basically what I ended up doing (with assert). It's just too bad because that would be a perfect usage of an enum, to validate ranges of explicit variables at compile time...
    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;
    }

  8. #8
    Evil Member
    Join Date
    Jan 2002
    Posts
    638
    Would be interesting, but that just ain't how it works...

    Mostly because in almost all cases you can't base behavior on the fact that something is a compile time constant and not a variable value based on some kind of input.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    No, but in this case, it would be...

    /*edit*/

    Windows defines several hundred numerical macros, which is the target of this experiment...
    Last edited by Sebastiani; 11-02-2002 at 11:20 PM.
    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
    Evil Member
    Join Date
    Jan 2002
    Posts
    638
    Well, don't you find it logical that code based on Windows code would behave in a less than optimal fashion?



    And enums are useful for a number of things, but data validation is NOT one of them. You could use a class HATCH with a constructor taking an int that would throw and exception if the int was out of range, but in most cases you are better off simply using acceptable values.

    btw... How would you not be able to code around an out of range compile time constant? That seems so very odd that any compile time constant could possibly be out of range, unless you for some reason wanted it to be.

  11. #11
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Well, let's say you were coding a windows program and were creating a certain brush. Now if you were certain that WHITE_BRUSH was a valid constant, then I would want you to be able to do:

    brush.MakeStock(WHITE_BRUSH);

    However, let's say you forgot the name of the constant and compiled this:

    brush.MakeStock();

    The compiler simply tells you it's an int. But using an enum, you would get:

    canidates are: MakeStock(Brush::STOCK)

    So you try:

    brush.MakeStock(Brush::CROSS);

    And you'd get:

    no matching call to MakeStock(Brush::HATCH), canidates Brush::STOCK, etc.

    But of course, typing:

    brush.MakeStock(Brush::WHITE);

    would compile fine and you'd know you were on track

    Silly, I know, but nonetheless a feature I'd love to see.

    So basically, since the enums and Windows constants have identical values, I wanted to give the user the option to use 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;
    }

  12. #12
    Evil Member
    Join Date
    Jan 2002
    Posts
    638
    Ah.. so you want to set up a situation to make the error generated by the compiler a better description of the problem... to make a program more AUTHOR friendly....

    Interesting...

  13. #13
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Thumbs up

    ...precisely...
    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;
    }

  14. #14
    S Sang-drax's Avatar
    Join Date
    May 2002
    Location
    Göteborg, Sweden
    Posts
    2,072
    There's a solution, instead of an enum, create a class.
    Code:
    class Object {
    public:
    
      class STYLE
      {
        public: 
         STYLE(int i_style)
         {
            if (i_style > 3) throw InvalidSTYLEException();
            style = i_style;
         }
        private:
          int style;
      };
      
      static STYLE SOLID,NUL,HATCHED,PATTERN;
    
     /*The same with HATCH*/
    
    
    bool MakeHatched( HATCH style ) {
      //...
     }
    };
    
    STYLE Object::SOLID = 0;
    STYLE Object::NUL = 1;
    /*etc.*/

    Btw, Sebastiani, will your library be platform-independent or only work in Windows?
    Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling

  15. #15
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Excellent solution there, Sang-Drax. I was thinking of using a static class but wasn't sure how to implement it...
    ...and no the library won't be platform independant (although I sure wish it was!). Er, or was that and offer? Heh...
    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;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 03-10-2008, 11:57 AM
  2. Moving Average Question
    By GCNDoug in forum C Programming
    Replies: 4
    Last Post: 04-23-2007, 11:05 PM
  3. Working with random like dice
    By SebastionV3 in forum C++ Programming
    Replies: 10
    Last Post: 05-26-2006, 09:16 PM
  4. Half-life SDK, where are the constants?
    By bennyandthejets in forum Game Programming
    Replies: 29
    Last Post: 08-25-2003, 11:58 AM
  5. Quack! It doesn't work! >.<
    By *Michelle* in forum C++ Programming
    Replies: 8
    Last Post: 03-02-2003, 12:26 AM