Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
505 views
in Technique[技术] by (71.8m points)

templates - C++ compile-time constant detection

There're cases when a library source is available, and it has to support variable parameters in general, but in practice these parameters are commonly constants.

Then it may be possible to optimize things by special handling of constant parameters (eg. use static arrays instead of heap allocation), but for that its necessary to determine whether something is a constant first (or maybe define some macros, but its less convenient).

So here's a working implementation.

Update: also here: http://codepad.org/ngP7Kt1V

  1. Is it really a valid C++ ?
  2. Is there a way to get rid of these macros? (is_const() can't be a function because the function dependence won't work in array size expression; also it can't be a template because that won't accept a variable parameter either. )

Update: Here's an update with something more like intended usage. The compiler won't generate any code for the if(N==0) branch if N is not 0. Same way we can switch to completely different data structures if we want. Sure its not perfect, but that's why I posted this question.


 #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
", buf, N, N1 );
}

#define testwrap(N) test< const_switch_word(N,0) >( N )

int main( void ) {
  printf( "%i %i %i
", X1, is_const(X1), sizeof(Y1) );
  printf( "%i %i %i
", X2, is_const(X2), sizeof(Y2) );
  testwrap( X1 );
  testwrap( X2 );
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you're working with GCC, use __builtin_constant_p to tell you whether something is a compile time constant. The documentation includes examples like

static const int table[] = {
  __builtin_constant_p (EXPRESSION) ? (EXPRESSION) : -1,
  /* ... */
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...