Бывают случаи, когда доступен источник библиотеки и он должен поддерживать параметры переменных в целом, но на практике эти параметры обычно являются константами.
Тогда можно будет оптимизировать вещи с помощью специальной обработки постоянных параметров (например, использования статических массивов вместо выделения кучи), но для этого необходимо сначала определить, является ли что-то константой (или, может быть, определить некоторые макросы, но это менее удобно ).
Итак, вот рабочая реализация.
Обновление: также здесь: 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()
работает только для x ›= 0, однако уловка (сделать результат неопределенным во время компиляции) работает и сis_const(X) | is_const(-X)
, поэтому is_const работает только дляall x: x!=INT_MIN
. - person Nordic Mainframe   schedule 21.07.2010sizeof(int)
иsizeof(char)
не обязательно будут разными (и есть реальные процессоры, где они одинаковы), поэтому вам следует использовать что-то вродеchar[2]
. (С другой стороны, я вижу жестко запрограммированные константы, поэтому полагаю, что переносимость не вызывает беспокойства.) - person ymett   schedule 04.08.2011