64-битное перечисление в С++?

Есть ли способ иметь 64-битное перечисление в С++? Во время рефакторинга некоторого кода я наткнулся на кучу #define, которые были бы лучше в качестве перечисления, но из-за того, что они больше 32 бит, компилятор выдает ошибку.

Я почему-то думал, что следующее может сработать:

enum MY_ENUM : unsigned __int64  
{  
    LARGE_VALUE = 0x1000000000000000,  
};

person Rob    schedule 16.09.2008    source источник
comment
Есть ли причина предпочесть unsigned __int64 uint64_t? Я думаю, что uint64_t определено почти для каждой соответствующей платформы, но unsigned __int64 звучит как определение платформы (аппаратного обеспечения, компилятора или даже библиотеки).   -  person Johan    schedule 07.04.2017
comment
@Johan __int64 — это псевдоним Microsoft-C++ для long long.   -  person ManuelAtWork    schedule 17.03.2021


Ответы (10)


Я не думаю, что это возможно с С++ 98. Базовое представление перечислений зависит от компилятора. В этом случае лучше использовать:

const __int64 LARGE_VALUE = 0x1000000000000000L;

Начиная с C++11, можно использовать классы перечисления для указания базового типа перечисления:

enum class MY_ENUM : unsigned __int64 {
    LARGE_VALUE = 0x1000000000000000ULL
};

Кроме того, классы enum вводят новую область имен. Поэтому вместо ссылки на LARGE_VALUE вы бы ссылались на MY_ENUM::LARGE_VALUE.

person Ferruccio    schedule 16.09.2008
comment
Это то, к чему я прибег в конце концов, но мне было любопытно, возможны ли 64-битные перечисления, даже с расширением, специфичным для компилятора. - person Rob; 17.09.2008
comment
MSVC 8 (2005) уже поддерживает базовый тип как нестандартное расширение. - person ManuelAtWork; 31.03.2021

С++ 11 поддерживает это, используя следующий синтаксис:

enum class Enum2 : __int64 {Val1, Val2, val3};
person Leon Timmermans    schedule 16.09.2008
comment
Я был близок тогда. Я должен где-то прочитать о синтаксисе : type. - person Rob; 17.09.2008
comment
обратите внимание, что class по-прежнему является необязательным. Если вам нужно перечисление в старом стиле, но с пользовательским типом, вы также можете enum moo : long long {...} - person Sebastian Mach; 10.02.2010

Текущий черновик так называемого C++0x, это n3092 говорится в 7.2 Объявления перечисления, пункт 6:

Какой целочисленный тип используется в качестве базового типа, определяется реализацией, за исключением того, что базовый тип не должен быть больше, чем int, если только значение перечислителя не может поместиться в int или unsigned int.

В этом же абзаце также говорится:

Если ни один целочисленный тип не может представить все значения перечислителя, перечисление имеет неправильный формат.

Моя интерпретация части если значение перечислителя не может поместиться в int или unsigned int, заключается в том, что совершенно допустимо и безопасно инициализировать перечислитель с 64-битным целочисленным значением, пока существует 64-битное значение. целочисленный тип, предоставляемый в конкретной реализации C++.

Например:

enum MyEnum
{
    Undefined = 0xffffffffffffffffULL
};
person mloskot    schedule 13.04.2010
comment
Если вы не хотите считать свои f, вы можете просто сделать Undefined = ~0x0ULL - person Cory-G; 01.08.2014

Ответы, относящиеся к __int64, упускают проблему. Перечисление допустимо во всех компиляторах C++ с истинным 64-битным интегральным типом, т. е. в любом компиляторе C++11 или компиляторе C++03 с соответствующими расширениями. Расширения C++03, такие как __int64, работают по-разному в разных компиляторах, включая его пригодность в качестве базового типа для перечислений.

person MSalters    schedule 17.09.2008

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

Вы можете создать что-то вроде в своем образце что-то вроде:

namespace MyNamespace {
const uint64 LARGE_VALUE = 0x1000000000000000;
};

и используя его так же, как перечисление, используя

MyNamespace::LARGE_VALUE 

or

using MyNamespace;
....
val = LARGE_VALUE;
person INS    schedule 16.09.2008
comment
И свободная безопасность типов, однако. - person Sebastian Mach; 10.02.2010
comment
Скорость нашего разговора напоминает мне шахматы по переписке :D - person Sebastian Mach; 14.07.2011

Поскольку вы работаете на C++, другой альтернативой может быть

const __int64 LARVE_VALUE = ...

Это можно указать в файле H.

person Torlack    schedule 16.09.2008
comment
Я накрутил 9 символов с первого раза. - person Behrooz; 22.04.2010

ваш фрагмент кода не соответствует стандарту С++:

перечисление MY_ENUM: без знака __int64

не имеет смысла.

вместо этого используйте const __int64, как предлагает Торлак

person ugasoft    schedule 16.09.2008
comment
он часто видел это в другом языке фигурных скобок (например, C# поддерживает его) или в готовящемся стандарте C++, где это будет разрешено. - person Sebastian Mach; 10.02.2010

Тип перечисления обычно определяется типом данных первого инициализатора перечисления. Если значение должно превышать диапазон для этого целочисленного типа данных, тогда компилятор С++ убедится, что оно подходит, используя более крупный целочисленный тип данных. Если компилятор обнаружит, что оно не принадлежит ни к какому целочисленному типу данных, компилятор выдаст ошибку. Ссылка: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf
Редактировать: Однако это зависит исключительно от архитектуры машины.

person human.js    schedule 07.12.2012

Перечисление в C++ может быть любого целочисленного типа. Вы можете, например, иметь перечисление символов. IE:

enum MY_ENUM
{
   CHAR_VALUE = 'c',
};

Я бы предполагал, что это включает __int64. Попробуйте просто

enum MY_ENUM
{
   LARGE_VALUE = 0x1000000000000000,
};

Согласно моему комментатору, sixlettervariables, в C базовым типом всегда будет int, а в C++ базовым типом будет все, что достаточно велико, чтобы соответствовать наибольшему включенному значению. Таким образом, оба перечисления выше должны работать.

person Doug T.    schedule 16.09.2008
comment
@Doug T.: в то время как ANSI C требует, чтобы перечисления имели размер типа данных «int», ISO C++ требует, чтобы размер перечислений был не меньше размера, необходимого для представления всех значений. - person user7116; 17.09.2008

В MSVC++ вы можете сделать это:

перечисление MYLONGLONGENUM:__int64 { BIG_KEY=0x3034303232303330, ... };

person Community    schedule 24.09.2009