【问题标题】:Static Assert to check compile-time-constant is NOT passed to macro用于检查编译时常量的静态断言未传递给宏
【发布时间】:2012-11-30 11:37:07
【问题描述】:

序言:

switch(nValue)
{
case X:
...
case Y:
...
default:
   ASSERT_FOR_DEFAULT(nValue);
}

ASSERT_FOR_DEFAULT 是一个宏,它将显示一个(自定义)断言对话框,以报告命中“默认情况”。是的,这个宏用于运行时断言,而不是编译时断言。但是,我只需要这样,任何常量值(编译时)都不能传递给这个宏。

问题:

以下应该在编译时失败

ASSERT_FOR_DEFAULT(5);

是的,程序员可以在任何地方使用它,而不仅仅是defaultswitch-case。他还可以使用switch 中未使用的任何表达式。但这不是问题。只需要将非常量传递给该宏即可。

没有为这个宏写任何重要的东西,假设它是ASSERT/assert

我尝试过使用模板(使用其他 SFINAE/static-asserts!)、数组(如 strcpy_s)、拥有 YESNO 类型的自己的结构等等。但找不到解决办法!

我正在使用 VC2008。我知道static_assertdecltype 等,但不能使用 C++0x。


编辑(解决方案):

#define STATIC_ASSERT(expr) {int array[!!(expr)]; expr;}

template <class T>  
bool noConstAllowed(T&);

int noConstAllowed(...);

#define ASSERT_FOR_DEFAULT_VALUE(val)                \
{                                                  \
    STATIC_ASSERT(sizeof(noConstAllowed(val))==sizeof(bool));   \
}

int main()
{
    int test=10;

    ASSERT_FOR_DEFAULT_VALUE(test);
    ASSERT_FOR_DEFAULT_VALUE(2);
    ASSERT_FOR_DEFAULT_VALUE(test+2);  //FAILS, but okay for me! 
}

感谢 Arne Mertz 提出这个可爱的建议。我从中得出了解决方案。 noConstAllowed 对所有T&amp; 类型都进行了重载,如果传递了常量值,则会调用另一个重载。两者都有不同的返回类型,因此检查大小。模板化版本返回一个bool,它满足任何传递的变量的断言,并且对于任何常量或表达式都失败(因为返回类型将是int)。

【问题讨论】:

  • @aleguna,毫无意义的评论!我需要静态断言的表达式,而不是如何制作或使用静态断言。

标签: c++ visual-c++ sfinae static-assert compile-time-constant


【解决方案1】:

您可以重新定义宏,以便它获取参数的地址——这对于文字来说应该是失败的。但是,这不会阻止您传递常量变量,例如

const static int FIVE = 5;
ASSERT_FOR_DEFAULT(FIVE); // still works.

要禁止将所有种常量传递给您的宏,请调用一个通过非常量引用获取参数的函数:

template <class T>  void noConstAllowed(T&){};
#define ASSERT_FOR_DEFAULT_VALUE(val)                \
  {                                                  \
    (void*)&(val);         /* no literals*/          \
    noConstAllowed(val);   /* no constants at all */ \
    switchHitDefaultDialog(val, __FILE__, __LINE__); \
  }

我想你使用类似 FILE 或其他位置宏的东西,或者你会把它变成一个函数。其中,您只需要使用这两行之一。

【讨论】:

  • 好建议!您提供的解决方案不是静态断言,而是为“noConstAllowed”和 sizeof 提供重载、模板和不同的返回类型,我会为它制作一个 SA。
  • 成功了。谢谢!检查我编辑的问题以找到我找到的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-03
  • 2016-12-29
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
相关资源
最近更新 更多