Использование numeric_limits::max() в константных выражениях

Я хотел бы определить внутри класса константу, значение которой является максимально возможным 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. #P6# <блочная цитата> #P7# #P8#

Спасибо.


person FireAphis    schedule 29.04.2010    source источник
comment
вы можете использовать climits cplusplus.com/reference/clibrary/climits   -  person Anycorn    schedule 29.04.2010
comment
@aaa: Но climits плохо работает с шаблонами.   -  person UncleBens    schedule 29.04.2010
comment
@Дядя, к сожалению. в принципе можно обернуть определения в шаблоны, некоторые работы, но выполнимые. или увеличить integer_traits, я думаю, они уже предоставлены: integer_traits <>::const_max/const_min   -  person Anycorn    schedule 29.04.2010


Ответы (5)


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

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

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

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

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

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

person Georg Fritzsche    schedule 29.04.2010

Похоже на какой-то дефект...

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

person UncleBens    schedule 29.04.2010
comment
Для тех, кто интересуется, по-видимому, поддержка этого была добавлена ​​в Visual Studio 2015. Теперь, если бы я мог просто обновить ИТ-отдел с 2013 года... - person Phlucious; 25.05.2017

Вы хотите:

#include <limits>

struct A {
static const int ERROR_VALUE;
}; 

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

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

person Community    schedule 29.04.2010
comment
можно ли использовать ERR_VALUE, как указано выше, в качестве аргумента шаблона? - person Anycorn; 29.04.2010
comment
Чем отличается инициализация внутри класса от внешней? Я знаю, что могу инициализировать константы внутри класса целыми значениями. Кроме того, у меня должен быть хотя бы один экземпляр такого класса, верно? В противном случае компилятор может решить не инициализировать его? - person FireAphis; 29.04.2010
comment
Пометка: нет ли здесь какой-либо библиотеки (возможно, boost), которая переопределяет эти значения, чтобы их можно было использовать в программировании меташаблонов? Было бы разумно иметь их в нашем распоряжении во время компиляции... - person Matthieu M.; 29.04.2010
comment
@aaa Нет, но он не об этом спрашивал. - person ; 29.04.2010
comment
@FireAphis Нет, вам не нужен экземпляр класса - он статичен! - person ; 29.04.2010
comment
@Matt boost.org/doc/libs/1_40_0/boost/integer_traits. Член hpp integer_traits‹›::const_max делает это. @Нил, мне просто было любопытно - person Anycorn; 29.04.2010

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

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

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

person Johannes Schaub - litb    schedule 29.04.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));
}

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

person Betamoo    schedule 29.04.2010
comment
Вместо числового значения 8 используйте макрос CHAR_BIT из climits (limits.h). - person Aconcagua; 24.02.2016