Có trường hợp khi nguồn thư viện khả dụng và nó phải hỗ trợ các tham số biến nói chung, nhưng trong thực tế, các tham số này thường là hằng số. Sau đó, có thể tối ưu hóa mọi thứ bằng cách xử lý đặc biệt các tham số không đổi (ví dụ: sử dụng các mảng tĩnh thay vì phân bổ đống), nhưng cần thiết để xác định xem có gì không phải là đầu tiên hay không (hoặc có thể xác định một số macro). nhưng ít thuận tiện hơn).Phát hiện liên tục biên dịch C++
Vì vậy, đây là triển khai hoạt động.
Cập nhật: cũng ở đây: http://codepad.org/ngP7Kt1V
- Có thực sự là một C++ hợp lệ?
- Có cách nào để loại bỏ các macro này không? (is_const() không thể là hàm bởi vì sự phụ thuộc hàm sẽ không hoạt động trong biểu thức kích thước mảng, cũng không thể là mẫu vì nó cũng không chấp nhận tham số biến.)
Cập nhật: Đây là bản cập nhật với nội dung nào đó giống như mục đích sử dụng. Trình biên dịch sẽ không tạo ra bất kỳ mã nào cho chi nhánh if(N==0)
nếu N
không phải là 0. Cùng một cách chúng ta có thể chuyển sang cấu trúc dữ liệu hoàn toàn khác nếu chúng ta muốn. Chắc chắn nó không hoàn hảo, nhưng đó là lý do tại sao tôi đăng câu hỏi này.
#include <stdio.h>
struct chkconst {
struct Temp { Temp(int x) {} };
static char chk2(void*) { return 0; }
static int chk2(Temp ) { return 0; }
};
#define is_const_0(X) (sizeof(chkconst::chk2(X))<sizeof(int))
#define is_const_0i(X) (sizeof(chkconst::chk2(X))>sizeof(char))
#define is_const(X) is_const_0((X)^((X)&0x7FFFFFFF))
#define const_bit(X1,bit) (is_const_0i((X1)&(1<<bit))<<bit)
#define const_nibl(X1,bit) const_bit(X1,bit) | const_bit(X1,(bit+1)) | const_bit(X1,(bit+2)) | const_bit(X1,(bit+3))
#define const_byte(X1,bit) const_nibl(X1,bit) | const_nibl(X1,(bit+4))
#define const_word(X1,bit) const_byte(X1,bit) | const_byte(X1,(bit+8))
#define const_uint(X1) const_word(X1,0) | const_word(X1,16)
#define const_switch_word(X1, X2) (is_const(X1) ? const_word(X1,0) : X2)
#define const_switch_uint(X1, X2) (is_const(X1) ? const_uint(X1) : X2)
const int X1 = 222;
const int X2 = printf("") + 333;
char Y1[ const_switch_word(X1,256) ];
char Y2[ const_switch_word(X2,256) ];
template< int N >
void test(int N1) {
char _buf[N>0?N:1];
char* buf = _buf;
if(N==0) {
buf = new char[N1];
}
printf("%08X %3i %3i\n", buf, N, N1);
}
#define testwrap(N) test< const_switch_word(N,0) >(N)
int main(void) {
printf("%i %i %i\n", X1, is_const(X1), sizeof(Y1));
printf("%i %i %i\n", X2, is_const(X2), sizeof(Y2));
testwrap(X1);
testwrap(X2);
}
'is_const()' làm việc cho x> = 0 chỉ, tuy nhiên mẹo (tạo kết quả biên dịch không xác định) hoạt động với 'is_const (X) | is_const (-X) 'quá, do đó có is_const chỉ làm việc cho' tất cả x: x! = INT_MIN'. –
Lưu ý rằng 'sizeof (int)' và 'sizeof (char)' không được bảo đảm khác (và có các bộ xử lý thực tế trong đó chúng giống nhau), vì vậy bạn nên sử dụng cái gì đó như 'char [2]'. (Mặt khác, tôi thấy các hằng số được mã hóa cứng nên tôi cho rằng tính di động không phải là một mối quan tâm.) – ymett
Mã tuyệt vời, ý tưởng tuyệt vời (tôi đoán nguồn gốc là http://encode.ru/threads/396-C-compile-time -constant-detection?) Tôi đã điều chỉnh mã is_const để có thể di chuyển hơn một chút (các vấn đề về sizeof char, INT_MAX được sử dụng), để xử lý tất cả các giá trị đầu vào có thể, và tạo ra một phiên bản không gcc đơn giản hơn - xem http://stackoverflow.com/questions/7658060/ có thể-i-sử dụng-giả-gơ-để-elide-a-gọi-nếu-một-điều kiện-được-biết-tại-biên dịch/7658363 # 7658363 – Suma