2015-10-31 18 views
2

我有这个功能实现零覆盖的东西,它使用static_assert来检查,如果给定的事情的类型是POD类型:如何设置一个static_assert的评估前提条件?

template <bool safeMode = true, typename generic> 
void overwriteWithZeros(generic *variableAddress) 
{ 
    if (safeMode) static_assert(std::is_pod<generic>::value, "Only POD types can be properly overwriten"); 

    const size_t size = sizeof(generic); 
    unsigned char *variableData = (unsigned char*)(variableAddress); 

    for (size_t i = 0; i < size; i++) 
     variableData[i] = 0; 
} 

我称之为这里:

int main() 
{ 
    being *creature = new being(100, "a guinea pig"); // being is not a POD type 

    overwriteWithZeros<false>(creature); 
    // totally unrelated stuff... 
} 

而且由于safeMode是编译时间值,我不知道它为什么会发生这种情况是真的还是假的,static_assert总是“发生”,给我不是POD类型的预期错误,就好像在static_assert之前的if简单地wasn在那里。

那么,我在这里做错了什么?

既然你证实了我的怀疑(if本身在运行时尽管safeMode是一个编译时的值或者不评估,而static_assert是在编译时计算的),我改变了主要问题:

什么我能做些什么来实现我在这里尝试的吗?

+6

因为'if'在运行时被评估,'static_assert'在编译时被评估。 –

+0

*“我能做些什么来实现我在这里尝试的功能”* - 'static_assert'不需要任何费用。删除'safeMode'参数并无条件保留断言。 –

+0

我可以做到这一点,但我想要一个开关来启用类型的安全检查,所以如果你真的想覆盖一些不是POD的东西,你可以这样做,并采取后果。 –

回答

6

问题是static_assert是在编译时评估的,这意味着当编译器找到它时,它会对它进行评估,而不管它在哪里(除非它被像#ifdef这样的宏排除)。为了解决这个问题,你应该评估自身的启用标志部分:

static_assert(!safeMode || std::is_pod<generic>::value, "Only POD types can be properly overwriten"); 

这是允许的,因为safeMode是编译时间值(是一个模板参数)。

在这两种情况下static_assert将被评估,但safeMode == false它总是评估为true

+0

我正是这么想的,因为safeMode是一个编译时间值,所以我试图做的事情可能已经奏效......所以当它没有时,我对什么可以做... –

+1

事实是一个编译时间常量不会改变if语句的语义。唯一的区别是,优化分支'if(false)'会从生成的代码中消失。但是这会在编译之后发生,并且在任何情况下'static_assert'不会发出任何代码。 – Jack

2

static_assert意思是说,断言是在编译时静态完成的。