Есть случаи, когда доступен источник библиотеки, и он должен поддерживать переменные параметры в целом, но на практике эти параметры обычно являются константами.Обнаружение постоянной времени компиляции C++
Тогда может быть возможно оптимизировать ситуацию путем специальной обработки постоянных параметров (например, использовать статические массивы вместо распределения кучи), но для этого необходимо определить, является ли что-то константой сначала (или, возможно, определить некоторые макросы, но его менее удобно).
Итак, это рабочая реализация.
Обновление: также здесь: http://codepad.org/ngP7Kt1V
- Является ли это на самом деле действительный C++?
- Есть ли способ избавиться от этих макросов? (Is_const() не может быть функцией, так как функция зависимость не будет работать в выражении размера массива;. Также он не может быть шаблоном, потому что не будет принимать переменное либо параметр)
Обновление: Вот обновление с чем-то более похожим на предполагаемое использование. Компилятор не будет генерировать код для ветки if(N==0)
, если N
не 0. Так же мы можем переключиться на совершенно разные структуры данных, если хотим. Уверен, что это не идеально, но поэтому я разместил этот вопрос.
#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()' работает при х> = 0 только, однако трюк (делают результат во время компиляции не определено) работает с 'is_const (X) | is_const (-X) ', так что is_const работает только для' all x: x! = INT_MIN'. –
Обратите внимание, что 'sizeof (int)' и 'sizeof (char)' не гарантируется быть разными (и есть реальные процессоры, где они одинаковые), поэтому вы должны использовать что-то вроде 'char [2]'. (С другой стороны, я вижу жестко закодированные константы, поэтому я полагаю, что переносимость не вызывает беспокойства.) – ymett
Отличный код, отличная идея (я думаю, исходный источник http://encode.ru/threads/396-C-compile-time -константа обнаружения?). Я адаптировал код is_const, чтобы быть немного более переносимым (sizeof char issues, INT_MAX), чтобы обрабатывать все возможные входные значения и создал более простую версию без gcc - см. Http://stackoverflow.com/questions/7658060/ can-i-use-accept-hint-to-elide-a-call-if-an-edge-condition-is-known-at-compile/7658363 # 7658363 – Suma