Почему C ++ поддерживает шестнадцатеричное назначение, но не имеет двоичного назначения? Как лучше всего хранить флаги?

У меня есть набор битовых флагов, которые используются в программе, которую я портирую с C на C ++.

Для начала ...

Флаги в моей программе ранее были определены как:

/* Define feature flags for this DCD file */
#define DCD_IS_CHARMM       0x01
#define DCD_HAS_4DIMS       0x02
#define DCD_HAS_EXTRA_BLOCK 0x04

... Теперь я понял, что #defines для констант (по сравнению с константами классов и т. Д.) Обычно считаются плохим тоном.

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

Я видел одно простое решение - просто создать отдельные константы:

namespace DCD {
   const unsigned int IS_CHARMM = 1;
   const unsigned int HAS_4DIMS = 2;
   const unsigned int HAS_EXTRA_BLOCK = 4;
};

Назовем эту идею 1.

Другая идея, которая у меня была, заключалась в использовании целочисленного перечисления:

namespace DCD {
   enum e_Feature_Flags {
      IS_CHARMM = 1,
      HAS_4DIMS = 2,
      HAS_EXTRA_BLOCK = 8
   };
};

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

namespace DCD {
   enum e_Feature_Flags {
      IS_CHARMM = 1,
      HAS_4DIMS = 2,
      HAS_EXTRA_BLOCK = 8,
      NEW_FLAG = 16,
      NEW_FLAG_2 = 32,
      NEW_FLAG_3 = 64,
      NEW_FLAG_4 = 128
   };
};

Назовем этот подход вариантом 2.

Я подумываю использовать макрорешение Тома Торфа:

#define B8(x) ((int) B8_(0x##x))

#define B8_(x) \
( ((x) & 0xF0000000) >( 28 - 7 ) \
| ((x) & 0x0F000000) >( 24 - 6 ) \
| ((x) & 0x00F00000) >( 20 - 5 ) \
| ((x) & 0x000F0000) >( 16 - 4 ) \
| ((x) & 0x0000F000) >( 12 - 3 ) \
| ((x) & 0x00000F00) >( 8 - 2 ) \
| ((x) & 0x000000F0) >( 4 - 1 ) \
| ((x) & 0x0000000F) >( 0 - 0 ) )

преобразовано во встроенные функции, например

#include <iostream>
#include <string>
....

/* TAKEN FROM THE C++ LITE FAQ [39.2]... */
class BadConversion : public std::runtime_error {
 public:
   BadConversion(std::string const& s)
     : std::runtime_error(s)
     { }
};

inline double convertToUI(std::string const& s)
{
   std::istringstream i(s);
   unsigned int x;
   if (!(i >> x))
     throw BadConversion("convertToUI(\"" + s + "\")");
   return x;
} 
/** END CODE **/

inline unsigned int B8(std::string x) {
   unsigned int my_val = convertToUI(x.insert(0,"0x").c_str());
   return ((my_val) & 0xF0000000) >( 28 - 7 ) |
            ((my_val) & 0x0F000000) >( 24 - 6 ) | 
            ((my_val) & 0x00F00000) >( 20 - 5 ) |
            ((my_val) & 0x000F0000) >( 16 - 4 ) |
            ((my_val) & 0x0000F000) >( 12 - 3 ) |
            ((my_val) & 0x00000F00) >( 8 - 2 ) |
            ((my_val) & 0x000000F0) >( 4 - 1 ) |
            ((my_val) & 0x0000000F) >( 0 - 0 );
}

namespace DCD {
   enum e_Feature_Flags {
      IS_CHARMM       = B8("00000001"),
      HAS_4DIMS       = B8("00000010"),
      HAS_EXTRA_BLOCK = B8("00000100"),
      NEW_FLAG        = B8("00001000"),
      NEW_FLAG_2      = B8("00010000"),
      NEW_FLAG_3      = B8("00100000"),
      NEW_FLAG_4      = B8("01000000")
   };
};

Это безумие? Или это кажется более интуитивным? Назовем этот вариант 3.

Итак, резюмирую, мои общие вопросы:

1. Почему C ++ не поддерживает флаг значения «0b», аналогичный «0x»?
2. Какой стиль лучше всего определять флаги ...
i. Константы, заключенные в пространство имен.
ii. Перечисление беззнаковых целых чисел, назначенных напрямую в пространство имен.
iii. Перечисление целых чисел без знака, обернутое в пространство имен, назначенных с использованием читаемой двоичной строки.

Заранее спасибо! И, пожалуйста, не закрывайте эту тему как субъективную, потому что я действительно хочу получить помощь о том, какой стиль лучше всего и почему в C ++ отсутствует встроенная возможность двоичного назначения.


РЕДАКТИРОВАТЬ 1

Немного дополнительной информации. Я буду читать 32-битное поле из файла, а затем тестировать его с этими флагами. Так что имейте это в виду, когда публикуете предложения.

6
задан Jason R. Mick 30 September 2010 в 20:32
поделиться