【发布时间】:2011-03-19 00:12:41
【问题描述】:
在某些情况下,库源可用,它通常必须支持可变参数,但实际上这些参数通常是常量。
然后可以通过对常量参数的特殊处理来优化事物(例如,使用静态数组而不是堆分配),但是为此有必要首先确定某个事物是否是常量(或者可能定义一些宏,但是不太方便)。
所以这是一个有效的实现。
更新:也在这里:http://codepad.org/ngP7Kt1V
- 它真的是一个有效的 C++ 吗?
- 有没有办法摆脱这些宏? (is_const() 不能是函数,因为函数依赖在数组大小表达式中不起作用;它也不能是模板,因为它也不接受可变参数。)
更新:这是一个更像预期用途的更新。
如果N 不为0,编译器不会为if(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。跨度> -
请注意,
sizeof(int)和sizeof(char)不能保证是不同的(现实生活中的处理器是相同的),所以你应该使用类似char[2]的东西。 (另一方面,我看到硬编码的常量,所以我认为可移植性不是问题。) -
好代码,好主意(我猜原始来源是encode.ru/threads/396-C-compile-time-constant-detection?)。我已将 is_const 代码调整为更便携(sizeof char 问题,使用 INT_MAX),以处理所有可能的输入值,并创建了一个更简单的非 gcc 版本 - 请参阅 stackoverflow.com/questions/7658060/…
标签: c++ templates metaprogramming compile-time-constant