views:

102

answers:

4

Guys, I've just dipped in to limits.h by MS. I tried to check what's the return type for max() fnc and to my surprise I see something like this:

// TEMPLATE CLASS numeric_limits
template<class _Ty>
    class numeric_limits
        : public _Num_base
    {   // numeric limits for arbitrary type _Ty (say little or nothing)
public:
    static _Ty (__CRTDECL min)() _THROW0()
        {   // return minimum value
        return (_Ty(0));
        }

    static _Ty (__CRTDECL max)() _THROW0()
        {   // return maximum value
        return (_Ty(0));//EXACTLY THE SAME WHAT IN min<<------------------
        }
//... other stuff
};

so how is it possiple that in both min and max return does exactly the same? So does it mean if I would write makeSanwich() return (_Ty(0)) it would make a sandwich for me? How is it possible that having this same code just fnc names different we are getting different results?

+6  A: 

That’s not the relevant code.

numeric_limits<T> is specialized for the native integer types and in these specializations the relevant values/logic is implemented. Look there.

The above code is a blanket code for all non-specialized types and they will indeed return the same value for both min() and max(). Try it yourself:

struct foo {
    int x;
    foo(int x) : x(x) {}
};

bool operator ==(foo const& a, foo const& b) { return a.x == b.x; }

assert(std::numeric_limits<foo>::min() == std::numeric_limits<foo>::max());

… I’m not sure that this behaviour is mandated by the standard, though. The above code could equally provoke a compile-time error since numeric_limits hasn’t been specialized for foo.

Konrad Rudolph
+2  A: 

If you do some more looking, you'll probably find that there are specializations for specific types, and those specializations return more meaningful values.

Jerry Coffin
+2  A: 

This is implemented through template specialization. Probably, you'll find something like this elsewhere:

template<>
class numeric_limits<int> : public _Num_base {
    public:
        static int min() {
            return INT_MIN;
        }
        static int max() {
            return INT_MAX;
        }
};

If you use numeric_limits<int> the above specialization will be preferred over the general case. There are similar specializations for float, char etcetera.

Only if none of these match, the general case will be selected. In that case, the compiler will try to construct an object of type _Ty from the 0 constant. Why that is ever useful... I don't know. I would rather have a compilation error instead.

Thomas
+1  A: 

What you see is the "generic limits" for an undefined type. So its results are no relevant. If you look below, you'll see:

template<> class _CRTIMP2_PURE numeric_limits<char>
    : public _Num_int_base
    {   // limits for type char
public:
    typedef char _Ty;

    static _Ty (__CRTDECL min)() _THROW0()
        {   // return minimum value
        return (CHAR_MIN);
        }

    static _Ty (__CRTDECL max)() _THROW0()
        {   // return maximum value
        return (CHAR_MAX);
        }
// etc.

};

Which is the specialization of the generic template for the type char, which gives the result you need.

For example, when you write:

int iMax = std::numeric_limits<char>::max() ;

it will use the specialized version of numeric_limits at compile time, and thus, put CHAR_MAX's value into variable iMax.

paercebal