我之前根据参数是否为constexpr
. 我正在尝试解决该问题的令人失望的答案,以制作更智能的断言功能。这大致是我想要做的:
inline void smart_assert (bool condition) {
if (is_constexpr (condition))
static_assert (condition, "Error!!!");
else
assert (condition);
}
基本上,这个想法是编译时检查总是比运行时检查更好,如果可以在编译时检查。但是,由于内联和常量折叠之类的原因,我不能总是知道是否可以进行编译时检查。这意味着在某些情况下可能会assert (condition)
编译到assert(false)
并且代码只是在等待我运行它并在我发现有错误之前执行该路径。
因此,如果有某种方法可以检查条件是否为 constexpr(由于内联或其他优化),我可以static_assert
在可能的情况下调用,否则可以使用运行时断言。幸运的是,gcc 有内在函数,如果是 constexpr __builtin_constant_p (exp)
,它会返回 true 。exp
我不知道其他编译器是否有这个内在,但我希望这能解决我的问题。这是我想出的代码:
#include <cassert>
#undef IS_CONSTEXPR
#if defined __GNUC__
#define IS_CONSTEXPR(exp) __builtin_constant_p (exp)
#else
#define IS_CONSTEXPR(exp) false
#endif
// TODO: Add other compilers
inline void smart_assert (bool const condition) {
static_assert (!IS_CONSTEXPR(condition) or condition, "Error!!!");
if (!IS_CONSTEXPR(condition))
assert (condition);
}
#undef IS_CONSTEXPR
依赖于的static_assert
短路行为or
。如果IS_CONSTEXPR
为真,则static_assert
可以使用,条件为!true or condition
,与just 相同condition
。如果IS_CONSTEXPR
为假,则static_assert
不能使用,条件为!false or condition
,与 相同,true
忽略static_assert
。如果static_assert
由于不是 constexpr 而无法检查condition
,那么我会在我的代码中添加一个运行时assert
作为最后的努力。但是,这不起作用,因为不能在 a 中使用函数参数static_assert
,即使参数是constexpr
.
特别是,如果我尝试使用 gcc 编译会发生这种情况:
// main.cpp
int main () {
smart_assert (false);
return 0;
}
g++ main.cpp -std=c++0x -O0
一切正常,编译正常。没有没有优化的内联,所以IS_CONSTEXPR
是 false 并且static_assert
被忽略,所以我只得到一个运行时assert
语句(失败)。然而,
[david@david-desktop test]$ g++ main.cpp -std=c++0x -O1
In file included from main.cpp:1:0:
smart_assert.hpp: In function ‘void smart_assert(bool)’:
smart_assert.hpp:12:3: error: non-constant condition for static assertion
smart_assert.hpp:12:3: error: ‘condition’ is not a constant expression
一旦我打开任何优化并因此可能static_assert
被触发,它就会失败,因为我不能在static_assert
. 有没有办法解决这个问题(即使这意味着实现我自己的static_assert
)?我觉得我的 C++ 项目理论上可以从一个更智能的断言语句中获得相当多的好处,该语句可以尽早发现错误。
在一般情况下,制作类似函数的宏似乎smart_assert
并不能解决问题。它显然可以在这个简单的示例中工作,但condition
可能来自调用图上两级的函数(但constexpr
由于内联,编译器仍然知道),这遇到了使用函数参数的相同问题在一个static_assert
。