Tôi có một bộ cờ bit được sử dụng trong chương trình tôi đang chuyển từ C sang C++.Tại sao C++ hỗ trợ chuyển nhượng Hex, nhưng thiếu phân bổ nhị phân? Làm thế nào tốt nhất để lưu trữ cờ?
Để bắt đầu ...
Các cờ trong chương trình của tôi trước đây được định nghĩa là:
/* Define feature flags for this DCD file */
#define DCD_IS_CHARMM 0x01
#define DCD_HAS_4DIMS 0x02
#define DCD_HAS_EXTRA_BLOCK 0x04
... Bây giờ tôi đã thu thập rằng # định nghĩa cho các hằng số (so với hằng số lớp vv) thường được coi là hình thức xấu.
Điều này đặt ra câu hỏi về cách lưu trữ cờ bit tốt nhất trong C++ và tại sao C++ không hỗ trợ gán văn bản nhị phân cho int, như cho phép số hex được gán theo cách này (thông qua "0x"). Những câu hỏi này được tóm tắt ở cuối bài đăng này.
tôi có thể thấy một giải pháp đơn giản là chỉ cần tạo ra hằng cá nhân:
namespace DCD {
const unsigned int IS_CHARMM = 1;
const unsigned int HAS_4DIMS = 2;
const unsigned int HAS_EXTRA_BLOCK = 4;
};
Hãy gọi ý tưởng này 1.
Một ý tưởng tôi đã có được sử dụng một enum số nguyên:
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = 1,
HAS_4DIMS = 2,
HAS_EXTRA_BLOCK = 8
};
};
Nhưng một điều làm phiền tôi về điều này là nó ít trực quan hơn khi nói đến các giá trị cao hơn, có vẻ như ... tức là
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
};
};
Hãy gọi lựa chọn phương pháp này 2.
tôi đang xem xét sử dụng giải pháp vĩ mô Tom Torf của:
#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))
chuyển đổi sang nội tuyến chức năng, ví dụ
#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")
};
};
Điều này có điên không? Hay nó có vẻ trực quan hơn? Hãy gọi sự lựa chọn này 3.
Vì vậy, để tóm tắt, câu hỏi quá cong của tôi là:
1. Tại sao không phải C++ hỗ trợ một "0b" giá trị cờ, tương tự như "0x"?
2. Cách tốt nhất để xác định cờ ...
i. Không gian tên được bao bọc.
ii. Không gian tên được bao bọc bởi các int không dấu được gán trực tiếp.
iii. Không gian tên được bao bọc bởi các int không dấu được gán bằng chuỗi nhị phân có thể đọc được.
Cảm ơn trước! Và xin đừng đóng chủ đề này là chủ quan, bởi vì tôi thực sự muốn nhận được sự giúp đỡ về phong cách tốt nhất là gì và tại sao C++ thiếu khả năng phân công nhị phân.
EDIT 1
Một chút thông tin bổ sung. Tôi sẽ đọc một bitfield 32 bit từ một tập tin và sau đó kiểm tra nó với những lá cờ này. Vì vậy, hãy nhớ điều đó khi bạn gửi đề xuất.
Ý bạn là 'int bit unsigned int (n) {1 << (n);}' phải không? ;) –
@ Jason: Không; người khởi tạo điều tra viên phải là biểu thức không đổi; bạn không thể gọi một hàm trong một biểu thức liên tục, vì vậy nó phải là một macro. –
hrmm ... Tôi đoán đó là thời điểm tốt để sử dụng macro? –