下面是一个示例setup ...宏或模板CHECKEXPR_RETURNVAL(EXPR,VAL),它在返回VAL时检查EXPR是否为TRUE。如何让C++创建一个使用编译时检查常量和断言变量的表达式?
这是一个不同的地方有用的 - 就像这个高度简化的例子:
#define ISPOW2(VAL) ((0!=VAL)&&(0==(VAL&(VAL-1))))
#define _ALIGNPOW2(VAL,ALIGN) ((VAL+(ALIGN-1))&(~(ALIGN-1)))
#define ALIGNPOW2(VAL,ALIGN) CHECKEXPR_RETURNVAL(\
ISPOW2(ALIGN) , _ALIGNPOW2(VAL,ALIGN))
所以,难的是这样的:我想要做的,如果可能的编译时检查,如果该值不是在编译时确定的常量,然后执行运行时检查。
基本上,这个想法是尽快捕捉不好的参数;如果你可以在编译时捕获一个坏的参数,那比在运行时发现更好。而且,编译时版本对于常量初始值设定项是必需的。
这里是我的两个(失败)的尝试使在多个地方单机版的工作(作为一个常量数组的大小,作为一个枚举初始化,并与变量的函数)。不幸的是,它们只能在编译时(常量初始化)或运行时才工作 - 我想找出一个适用于这两者的版本。
// CHECKEXPR_RETURNVAL - version "A"
#define CTCHECK_EXPR(EXP)(CTCheckBool<EXP>::ExistsZeroIfTrue)
template <bool bExpression> struct CTCheckBool {};
template <> struct CTCheckBool<true> {enum{ExistsZeroIfTrue=0};};
// Note: Plus ("+") is used rather than comma operator because
// the comma operator can not be used for constant initializers
#define CHECKEXPR_RETURNVAL_A(EXP,VAL) (CTCHECK_EXPR(EXP) + (VAL))
// Test Out version "A" -- works only for Compile Time Constants
#define ALIGNPOW2_A(VAL,ALIGN) CHECKEXPR_RETURNVAL_A(\
ISPOW2(ALIGN) , _ALIGNPOW2(VAL,ALIGN))
char AlignedVar_A[ALIGNPOW2_A(2,8)];
enum { AlignedVal_A = ALIGNPOW2_A(57,16) };
int TestAlignPow2_A(int val, int align)
{return(ALIGNPOW2_A(val,align));} // Compile Error
// CHECKEXPR_RETURNVAL - version "B"
template<typename T> T CHECKEXPR_RETURNVAL_B(bool bExpr,T val)
{ ASSERT(bExpr); return(val); }
// Test Out version "B" -- works only for Runtime Computed Values
#define ALIGNPOW2_B(VAL,ALIGN) CHECKEXPR_RETURNVAL_B(\
ISPOW2(ALIGN) , _ALIGNPOW2(VAL,ALIGN))
char AlignedVar_B[ALIGNPOW2_B(2,8)]; // Compile Error
enum { AlignedVal_B = ALIGNPOW2_B(57,16) }; // Compile Error
int TestAlignPow2_B(int val, int align)
{return(ALIGNPOW2_B(val,align));}
不幸的是,两种版本都不适用于所有三种情况。是否有一个适用于所有情况的代码结构?
听起来类似于http://stackoverflow.com/questions/3299834/c-compile-time-constant-检测 – Shelwien 2010-08-03 22:19:58
@Neil:这只是我在几分钟内写出的一次性测试文件中试用的东西 - 它远不及产品代码。这些代码当然是非法的,而且不能运行 - 这就是为什么我注意到它没有编译的问题。我要问在所有三种情况下如何正确做到这一点。但是,我不明白如何能够验证(特别是在编译时)对宏的参数是否正确是如此可怕。也许你有什么建设性的补充关于如何实现一个ALIGNPOW2(VAL,ALIGN)宏,以合法的方式检查ALIGN是否为2的幂? – Adisak 2010-08-03 22:30:35
好的,您希望在返回VAL时测试EXPR是否为“TRUE”的模板或宏(如果表达式为“TRUE”,那么正确?)。好的。现在,如果表达式是“FALSE”,那么应该发生什么?空陈述?编译器错误? – SigTerm 2010-08-03 22:45:07