Есть ли способ иметь 64-битное перечисление в C++? Во время рефакторинга некоторого кода я наткнулся на кучу #defines, которые были бы лучше в качестве перечисления, но более 32 бит вызывают ошибку компилятора.
По какой-то причине я подумал, что может сработать следующее:
enum MY_ENUM : unsigned __int64
{
LARGE_VALUE = 0x1000000000000000,
};





Перечисление в C++ может быть любым целым типом. Вы можете, например, иметь перечисление символов. IE:
enum MY_ENUM
{
CHAR_VALUE = 'c',
};
Я бы сказал, что предполагать включает __int64. Попробуй просто
enum MY_ENUM
{
LARGE_VALUE = 0x1000000000000000,
};
По словам моего комментатора, sixlettervariables, в C базовым типом всегда будет int, а в C++ базовым типом будет все, что достаточно велико, чтобы соответствовать наибольшему включенному значению. Таким образом, оба перечисления выше должны работать.
@Doug T .: в то время как ANSI C диктует, что перечисления имеют размер типа данных 'int', ISO C++ диктует, что размер перечислений должен быть не меньше размера, необходимого для представления всех значений.
Я не думаю, что это возможно с C++ 98. Базовое представление перечислений зависит от компилятора. В этом случае вам лучше использовать:
const __int64 LARGE_VALUE = 0x1000000000000000L;
Начиная с C++ 11, можно использовать классы перечисления для указания базового типа перечисления:
enum class MY_ENUM : unsigned __int64 {
LARGE_VALUE = 0x1000000000000000ULL
};
Кроме того, классы перечисления вводят новую область имен. Поэтому вместо ссылки на LARGE_VALUE вы должны ссылаться на MY_ENUM::LARGE_VALUE.
Это то, к чему я прибег в конце концов, но мне было любопытно, возможны ли 64-битные перечисления, даже с конкретным расширением компилятора.
Поскольку вы работаете на C++, другой альтернативой может быть
const __int64 LARVE_VALUE = ...
Это можно указать в файле H.
Я обманул 9 символов с первой попытки.
Если компилятор не поддерживает 64-битные перечисления с помощью флагов компиляции или каких-либо других средств, я думаю, что для этого нет решения.
Вы можете создать в своем образце что-то вроде:
namespace MyNamespace {
const uint64 LARGE_VALUE = 0x1000000000000000;
};
и используя его так же, как перечисление, используя
MyNamespace::LARGE_VALUE
или же
using MyNamespace;
....
val = LARGE_VALUE;
И все же слабая безопасность типов.
Скорость нашего разговора мне напоминает заочные шахматы: D
ваш фрагмент кода не является стандартом С ++:
enum MY_ENUM : unsigned __int64
не имеет смысла.
вместо этого используйте const __int64, как предлагает Торлак
он часто видел это в другом языке фигурных скобок (например, C# поддерживает это) или в готовящемся стандарте C++, где это будет разрешено.
C++ 11 поддерживает это, используя следующий синтаксис:
enum class Enum2 : __int64 {Val1, Val2, val3};
Тогда я был близок. Я должен где-нибудь прочитать о синтаксисе : type.
обратите внимание, что class по-прежнему не является обязательным. Если вам нужно перечисление в старом стиле, но с настраиваемым типом, вы также можете enum moo : long long {...}
Ответы, относящиеся к __int64, упускают из виду проблему. Перечисление является допустимо во всех компиляторах C++, которые имеют истинный 64-битный целочисленный тип, то есть в любом компиляторе C++ 11 или компиляторах C++ 03 с соответствующими расширениями. Расширения C++ 03, такие как __int64, работают по-разному в разных компиляторах, включая его пригодность в качестве базового типа для перечислений.
В MSVC++ вы можете сделать это:
перечисление MYLONGLONGENUM: __ int64 {BIG_KEY = 0x3034303232303330, ...};
Текущий проект так называемого C++ 0x, это n3092, говорится в параграфе 6 7.2 Объявления перечисления:
It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int.
В том же абзаце также говорится:
If no integral type can represent all the enumerator values, the enumeration is ill-formed.
Моя интерпретация части если значение перечислителя не может поместиться в int или unsigned int заключается в том, что вполне допустимо и безопасно инициализировать перечислитель 64-битным целочисленным значением, если в конкретной реализации C++ предоставляется 64-битный целочисленный тип.
Например:
enum MyEnum
{
Undefined = 0xffffffffffffffffULL
};
Если вы не хотите отсчитывать свои f, вы можете просто сделать Undefined = ~0x0ULL
Тип перечисления обычно определяется типом данных первого инициализатора перечисления. Если значение должно превышать диапазон для этого интегрального типа данных, компилятор C++ обеспечит его соответствие, используя более крупный интегральный тип данных. Если компилятор обнаружит, что он не принадлежит ни к одному из интегральных типов данных, компилятор выдаст ошибку.
Ссылка: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf
Edit: Однако это полностью зависит от архитектуры машины.
Есть ли причина предпочесть
unsigned __int64передuint64_t? Я думаю, чтоuint64_tопределен почти для каждой соответствующей платформы, ноunsigned __int64звучит как определение конкретной платформы (аппаратного обеспечения, компилятора или даже библиотеки).