Достаточно ли правильного имени, чтобы это произошло? - PullRequest
3 голосов
/ 12 мая 2010

Я только что окунулся в limits.h от Microsoft. Я попытался проверить тип возврата для функции max() и, к моему удивлению, вижу что-то вроде этого:

// 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
};

Как возможно, что и в min, и в max возвращаются одинаково? Означает ли это, что если я напишу makeSanwich () return (_Ty (0)), это сделает для меня бутерброд? Как это возможно, что, имея один и тот же код с разными именами функций, мы получаем разные результаты?

Ответы [ 4 ]

6 голосов
/ 12 мая 2010

Это не соответствующий код.

numeric_limits<T> специализируется на собственных целочисленных типах, а в этих специализациях реализованы соответствующие значения / логика. Посмотри туда.

Приведенный выше код является общим кодом для всех неспециализированных типов, и они действительно будут возвращать одно и то же значение как для min(), так и max(). Попробуйте сами:

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());

… Хотя я не уверен, что такое поведение предписано стандартом. Приведенный выше код может также вызвать ошибку во время компиляции, поскольку numeric_limits не специализировался для foo.

2 голосов
/ 12 мая 2010

Это реализуется через специализацию шаблонов. Возможно, вы найдете что-то подобное в другом месте:

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

Если вы используете numeric_limits<int>, вышеуказанная специализация будет предпочтительнее, чем в общем случае. Есть похожие специализации для float, char и так далее.

Только если ни один из них не совпадает, будет выбран общий случай. В этом случае компилятор попытается создать объект типа _Ty из константы 0. Почему это всегда полезно ... Я не знаю. Вместо этого я предпочел бы иметь ошибку компиляции.

2 голосов
/ 12 мая 2010

Если вы посмотрите больше, вы, вероятно, обнаружите, что есть специализации для определенных типов, и эти специализации возвращают более значимые значения.

1 голос
/ 12 мая 2010

То, что вы видите, это «общие ограничения» для неопределенного типа. Так что его результаты не актуальны. Если вы посмотрите ниже, вы увидите:

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.

};

Это специализация универсального шаблона для типа char, которая дает необходимый результат.

Например, когда вы пишете:

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

он будет использовать специализированную версию numeric_limits во время компиляции и, таким образом, поместит значение CHAR_MAX в переменную iMax.

...