Thread: Float that initializes to NaN

  1. #1
    Registered User
    Join Date
    Nov 2011
    Posts
    24

    Float that initializes to NaN

    Hi! I want to make a class that works exactly like a float, only that it is initialized to NaN when the default constructor is called and if DEBUG is defined so that I can easily detect when I have an uninitialized float. Is there some simple way to do this? Thanks in advance!
    Last edited by then; 05-16-2012 at 09:24 AM.

  2. #2
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    I'm not sure if this is portable.
    Code:
    #ifdef DEBUG
    float_var = std::sqrt(-1);
    #endif
    I assume you encapsulate a float variable.
    If, on the other hand, you want to implement floating point numbers by yourself.. it is *much* more complicated and I have no idea.

    [EDIT]
    I just found out that there is a NAN macro in math.h .
    So, "foo = NAN;" would be a better idea .
    Last edited by manasij7479; 05-16-2012 at 09:36 AM.

  3. #3
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    Thank you, that is one way to generate a NaN, yes. But the question was how to make the kind of class I described above.

  4. #4
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by then View Post
    Thank you, that is one way to generate a NaN, yes. But the question was how to make the kind of class I described above.
    Just encapsulate a float variable and overload the operators.
    (And possibly throw some exceptions within them.)
    I don't think there is anything else to it.
    Last edited by manasij7479; 05-16-2012 at 09:40 AM.

  5. #5
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    I'm trying. So far I the class declaration looks like this:

    Code:
    template<typename T>
    class base_safe_float
    {
    public:
        /* Constructors */
        base_safe_float(); // Default constructor
        template<typename T2> base_safe_float<T>(T2 s); // Copy conversion constructor
    
        /* Conversion operator */
        operator T() const;
    
        /* Assignment operators */
        template<typename T2> base_safe_float<T>& operator =(const T2&);
        template<typename T2> base_safe_float<T>& operator+=(const T2&);
        template<typename T2> base_safe_float<T>& operator-=(const T2&);
        template<typename T2> base_safe_float<T>& operator*=(const T2&);
        template<typename T2> base_safe_float<T>& operator/=(const T2&);
    
    private:
        T v; /* Value */
    };
    I don't know if this is all constructors and operators I need to define. However, when I'm trying to use this, I'm getting errors like

    Code:
    error: operands to ?: have different types 'int' and 'ftype'
    (ftype is typedefd as base_safe_float<float>)

    It is complaining on the row

    Code:
    f = f < 0 ? 0 : f;
    where f is a variable of type ftype. How can I get rid of this error without modifying the line that's generating it (since the line shouldn't generate the error)?

    If the class is supposed to work exactly like a float (or as a double, depending on what the template argument is), I must find some way to get rid of all these compile errors.



  6. #6
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    don't forget about comparison (==, !=, <, >, <=, >=) operators

  7. #7
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    Quote Originally Posted by Elkvis View Post
    don't forget about comparison (==, !=, <, >, <=, >=) operators
    Doesn't the compiler realize that it can just use the conversion operator and then compare a float against whatever it is I want to compare it against?

  8. #8
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    I don't think you can make that assumption, not to mention implicit conversion operators, while legal in the code, are not recommended, as you may get unexpected results.

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I have the guts of a lightweight class that implements exactly enough to do this kind of thing already. I could have this made in about 10 minutes after work today. Might post back in about 10 hours with it.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #10
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    How can I get rid of this error without modifying the line that's generating it (since the line shouldn't generate the error)?
    O_o

    It should generate the error.

    Both results of the conditional operator are required to be the same type or convertible to the same type. The compiler is not allowed to choose the conversion. If the conversion can be assumed because the types have an inheritance relationship the compiler will implicitly convert a child class reference to a parent class reference. If the relationship between types are not direct one or both types must be explicitly cast.

    You need to explicitly cast the zero (an integer value) to type `T'.

    I don't think you can make that assumption, not to mention implicit conversion operators, while legal in the code, are not recommended, as you may get unexpected results.
    There is no problem in this context. The type of conversion is directly related to the type held by the class. Without the conversion the class can't be used as a real `float' could be used even if every other operator is provided.

    However, the other operators should still be provided. You can catch an uninitialized value without them; with them you can catch other semantic errors later.

    Soma

  11. #11
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    Quote Originally Posted by phantomotap View Post
    O_o
    I don't get this error when f just is a normal float, that is why a base_safe_float<float> shouldn't generate any error here either.

    Quote Originally Posted by phantomotap View Post
    However, the other operators should still be provided. You can catch an uninitialized value without them; with them you can catch other semantic errors later.

    Soma
    Okay. I have already started to write the other operators but I deactivated them since I didn't think they would contribute anything to the class when I had the conversion operator. But there are really many operators, should I overload all of them?

  12. #12
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    Quote Originally Posted by iMalc View Post
    I have the guts of a lightweight class that implements exactly enough to do this kind of thing already. I could have this made in about 10 minutes after work today. Might post back in about 10 hours with it.
    It would be interesting to see your implementation and if it differs something from my class (except from that my isn't finished yet).

  13. #13
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by then View Post
    It would be interesting to see your implementation and if it differs something from my class (except from that my isn't finished yet).
    I would also like to see either/both of the implementations.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  14. #14
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I don't get this error when f just is a normal float, that is why a base_safe_float<float> shouldn't generate any error here either.
    Your opinion is irrelevant.

    You are simply wrong.

    Code:
    f < 0 ? 0 : f;
    In this code that you posted the both results differ beyond what the compiler is allowed to infer.

    The compiler can't simply choose because both are perfectly valid.

    Code:
        f < 0 ? static_cast<ftype>(0) : f;
    Code:
        f < 0 ? 0 : static_cast<float>(f);
    These are both equally valid so the compiler is not allowed to choose.

    Code:
    (condition) ? (true_result) : (false_result);
    You are still wrong if you are just trying to say "The compiler should convert the class instance because a conversion operator is available." The conversion operator isn't considered here because the isolated expression `false_result' assumes no specific type.

    Code:
    class OBase
    {
    };
    
    class ODerived1:
        public OBase
    {
    };
    
    class ODerived2:
        public OBase
    {
    };
    
    int main()
    {
        ODerived1 * lD1(0);
        ODerived2 * lD2(0);
        OBase * lB1(lD1);
        OBase * lB2(lD2);
        OBase * lB3((true) ? (lD1) : (lD2));
        return(0);
    }
    You are also wrong if you think the target variable type has anything to do with it. The type that the result of the condition operator expression may be assigned isn't considered by the compiler; the type of the expression must be fixed in isolation.

    The upshot to all of this is that you must be explicit with respect to the types involved in a conditional operator expression. If you don't want to do this for whatever reason, you can't use the conditional operator; you would need to use a normal branch.

    Soma

  15. #15
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    Quote Originally Posted by phantomotap View Post
    Your opinion is irrelevant.

    You are simply wrong.
    So you should have an opinion that is relevant but not me? And I don't know what it was I wrote that you think is wrong. It is easy to just ignore the rest of what you are writing when you start your post with two quite provoking/disparaging statements; you know that, right?

    Apparently my compiler could chose between the two cases (although I don't know how it did it) and that is actually what matters to me. If it behaves in one way for float it should behave in the same way for the class I'm creating. I don't know what is correct behavior and which is not (which you seems to know), but I don't want it to change it when I switch type.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. (float) or (float*) wrt sizeOf()
    By jakemott in forum C Programming
    Replies: 2
    Last Post: 07-19-2009, 08:13 PM
  2. float value
    By munna_dude in forum C Programming
    Replies: 6
    Last Post: 06-22-2007, 11:25 AM
  3. Replies: 8
    Last Post: 07-08-2005, 09:12 AM
  4. initializes all components of failing to false
    By romeoz in forum C++ Programming
    Replies: 21
    Last Post: 08-01-2003, 09:30 PM
  5. Unresolved external 'convert(float, float)'
    By Ipsec Espah in forum C++ Programming
    Replies: 4
    Last Post: 05-21-2003, 10:08 AM

Tags for this Thread