Использование numeric_limits :: max () в константных выражениях - PullRequest
28 голосов
/ 29 апреля 2010

Я хотел бы определить внутри класса константу, значение которой является максимально возможным int. Примерно так:

class A
{
    ...
    static const int ERROR_VALUE = std::numeric_limits<int>::max();
    ...
}

Это объявление не может быть скомпилировано со следующим сообщением:

numeric.cpp: 8: ошибка: 'std :: numeric_limits :: max ()' не может появляться в константном выражении numeric.cpp: 8: ошибка: вызов функции не может появляться в константном выражении

Я понимаю, почему это не работает, но две вещи кажутся мне странными:

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

  2. В спецификации 18.2.1 заявлено, что

    Для всех членов, объявленных статическим const в шаблоне numeric_limits, специализации должны определять эти значения таким образом, чтобы их можно было использовать как целочисленные константные выражения.

    Разве это не значит, что я должен иметь возможность использовать его в моем сценарии, и не противоречит ли это сообщению об ошибке?

Спасибо.

Ответы [ 5 ]

16 голосов
/ 29 апреля 2010

Хотя текущему стандарту здесь не хватает поддержки, для целочисленных типов Boost.IntegerTraits дает вам константы времени компиляции const_min и const_max.

Проблема возникает из §9.4.2 / 4 :

Если статический член данных имеет константный интеграл или константный тип перечисления, его объявление в определении класса может указывать инициализатор константы, который должен быть выражением интегральной константы (5.19). В этом случае член может появляться в виде целочисленных константных выражений.

Обратите внимание, что добавляет:

Член по-прежнему должен быть определен в области имен, если он используется в программе, а определение области имен не должно содержать инициализатор.

Как уже упоминалось, numeric_limit s min() и max() просто не являются целочисленными константными выражениями, то есть константами времени компиляции.

16 голосов
/ 29 апреля 2010

Похоже, что-то вроде дефекта ...

В C ++ 0x numeric_limits будет иметь все, помеченное constexpr, что означает, что вы сможете использовать min() и max() в качестве констант времени компиляции.

13 голосов
/ 29 апреля 2010

Вы хотите:

#include <limits>

struct A {
static const int ERROR_VALUE;
}; 

const int A::ERROR_VALUE = std::numeric_limits<int>::max();

Поместите класс / структуру в заголовок, а определение в файл .cpp.

4 голосов
/ 29 апреля 2010

Это не противоречит, потому что max не определено static const. Это просто статическая функция-член. Функции не могут быть константными, и статические функции-члены также не могут иметь константное присоединение в самом правом углу.

В двойной версии ограничений также есть double max(), а в C ++ 03 было бы не сказать static double const max = .... Чтобы быть последовательным, max() - это функция для всех версий шаблона лимита.

Теперь известно, что max() не может быть использован таким образом, что это плохо, и C ++ 0x уже решает это, превращая его в constexpr функцию, позволяющую использовать ваше предложение.

2 голосов
/ 29 апреля 2010
  • Я постараюсь ответить вам так же, как я понял из вашего вопроса:

1- Если вы хотите, чтобы static const int в вашей программе инициализировался с помощью функции:

int Data()
{
 return rand();
}

class A
{
public :
    static const int ee;
};
const int A::ee=Data();

Это работает на VS 2008

2- Если вы хотите получить максимальное и минимальное число для данного типа данных, используйте эти определения INT_MAX, INT_MIN, LONG_MAX и т. Д ..

3 - Однако, если вам нужно использовать эти типы шаблонов, то Жесткий код самих шаблонов

template<>
int MaxData()
{
 return INT_MAX;
}

и

template<>
long MaxData()
{
 return LONG_MAX ;
}

и назовите их вот так

int y=MaxData<int>();

4- и если вы имеете дело только с двоичными представленными типами, используйте это:

template <class T>
T MaxData(){
    return ~(1<<((sizeof(T)*8)-1));
}

а это

template <class T>
T MinData(){
    return (1<<((sizeof(T)*8)-1));
}

Надеюсь, это поможет вам ..

...