Existen casos en los que una fuente de biblioteca está disponible y tiene que soportar parámetros variables en general, pero en la práctica estos parámetros son comúnmente constantes.Detección constante en tiempo de compilación en C++
Entonces puede ser posible optimizar cosas mediante el manejo especial de parámetros constantes (por ejemplo, usar matrices estáticas en lugar de asignación de montón), pero para eso es necesario determinar si algo es una constante primero (o quizás definir algunas macros, pero es menos conveniente).
Así que aquí hay una implementación en funcionamiento.
Actualización: también aquí: http://codepad.org/ngP7Kt1V
- ¿Es realmente un C++ válida?
- ¿Hay alguna manera de deshacerse de estas macros? (Is_const() no puede ser una función porque la dependencia función no funcionará en la expresión tamaño de la matriz;. También que no puede ser una plantilla porque que no aceptará un parámetro variable, ya sea)
Actualización: Aquí hay una actualización con algo más parecido al uso previsto. El compilador no generará ningún código para la rama if(N==0)
si N
no es 0. De la misma manera podemos cambiar a estructuras de datos completamente diferentes si lo deseamos. Claro que no es perfecto, pero es por eso que he publicado esta pregunta.
#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()' que funciona para x> = 0 solamente, sin embargo, el truco (Agrega resultado en tiempo de compilación no definido) trabaja con 'is_const (X) | is_const (-X) 'también, teniendo así is_const trabajando solo para' all x: x! = INT_MIN'. –
Tenga en cuenta que 'sizeof (int)' y 'sizeof (char)' no se garantiza que sean diferentes (y hay procesadores de la vida real donde son los mismos), por lo que debe usar algo como 'char [2]'. (Por otro lado, veo constantes codificadas, así que supongo que la portabilidad no es una preocupación). – ymett
Gran código, gran idea (creo que la fuente original es http://encode.ru/threads/396-C-compile-time -constant-detection?). He adaptado el código is_const para que sea un poco más portátil (tamaño de temas Char, INT_MAX utilizado), para manejar todos los valores de entrada posibles, y he creado una versión no-gcc más simple - ver http://stackoverflow.com/questions/7658060/ can-i-use-assume-hint-to-elide-a-call-if-an-edge-condition-is-known-at-compile/7658363 # 7658363 – Suma