C++ 如何最好地防止自定义断言中没有sizeof的未使用变量警告?
根据中的建议,我已经使用自己的assert版本(称为C++ 如何最好地防止自定义断言中没有sizeof的未使用变量警告?,c++,c++11,lambda,assert,sizeof,C++,C++11,Lambda,Assert,Sizeof,根据中的建议,我已经使用自己的assert版本(称为emp_assert)有一段时间了。因此,设置NDEBUG时,我的断言如下所示: #define emp_assert(EXPR) ((void) sizeof(EXPR) ) 此定义确保EXPR中的任何变量在编译器中仍被视为“已使用”,但不会影响运行时性能 不幸的是,我最近发现在断言中使用lambdas都会产生编译错误,因为lambdas不能放入sizeof中 我的选择似乎是: 只需去除sizeof;我的代码中很少有不使用变量的情况,只能手
emp_assert
)有一段时间了。因此,设置NDEBUG时,我的断言如下所示:
#define emp_assert(EXPR) ((void) sizeof(EXPR) )
此定义确保EXPR中的任何变量在编译器中仍被视为“已使用”,但不会影响运行时性能
不幸的是,我最近发现在断言中使用lambdas都会产生编译错误,因为lambdas不能放入sizeof中
我的选择似乎是:
#include <iostream>
#include <algorithm>
#include <vector>
#define NDEBUG
// Relevant excerpt from "emp_assert.h"
#ifdef NDEBUG
#define emp_assert(EXPR) ((void) sizeof(EXPR))
#else
#define emp_assert(EXPR) \
do { if ( !(EXPR) ) { \
std::cerr << "Assert Error (In " << __FILE__ \
<< " line " << __LINE__ \
<< "): " << #EXPR << std::endl; \
abort(); } \
} while (0)
#endif
// Code to trigger the problem (asserting that all ints in a vector are less than 8.)
int main()
{
std::vector<int> v = {1, 2, 3, 4, 8};
emp_assert( std::all_of(v.begin(), v.end(), [](int i){return i < 8;}) );
}
#包括
#包括
#包括
#定义NDEBUG
//“emp_assert.h”的相关摘录
#ifdef-NDEBUG
#定义emp_assert(EXPR)((void)sizeof(EXPR))
#否则
#定义emp_断言(EXPR)\
do{if(!(EXPR)){\
我相信我找到了一个解决方案。由于lambda表达式不允许出现在未赋值的操作数中,但允许出现在常量表达式的未赋值部分,我们应该能够利用这一事实
具体地说,我已经将我的#define when NDEBUG设置为:
#define emp_assert(EXPR) { \
constexpr bool __emp_assert_tmp = false && (EXPR); \
(void) __emp_assert_tmp; \
}
constepr
确保在编译时对表达式的其余部分求值。但是false&&(EXPR)
短路,因此永远不会对EXPR求值,但其中的变量不会被视为未使用
变量\uuuu emp\u assert\u tmp
是在它自己的作用域内创建的,因此多个断言不会冲突。高度特定的名称将确保我们不会意外地跟踪EXPR中使用的变量。任何合理的优化编译器都应该完全删除额外的变量,因此我认为它不会导致优化反倾销问题
在我的测试中,EXPR中没有执行任何内容,lambda不会出错,而且似乎一切都正常工作
如果您看到我缺少的任何问题,请告诉我。为什么使用sizeof
?在您的示例中,我看不到使用sizeof
的任何目的,为什么不这样定义:
#define emp_assert(exp) ((void) exp)
如果要防止未使用的变量警告,可以使用c++17属性抑制未使用实体上的警告。例如:
[[maybe_unused]]
auto l = [](int i){return i < 8;};
参见您的示例。emp_assert
的要点是什么?它与assert
或static_assert
有什么不同?两个主要区别:当我打开单元测试标志时,它报告错误而不中止(这样我就可以测试我的断言),以及当我使用Emscripten编译时(到asm.js)它使用Javascript警报来提供信息。您是否可以包含一些使用emp_assert
的代码并显示问题?向委员会提交一个bug,要求他们删除未赋值操作数中对lambda的限制?@T.C.看起来您是对的;这是一个实际的限制,因此无法找到和替换solu另一方面,这里对这个问题进行了很好的讨论,可能通过使用常量表达式提供了一些可能性:这将使odr使用EXPR
的子表达式,而不像sizeof
。为什么定义emp\u assert(EXPR){(void)EXPR;}
不够?sizeof()防止任何意外的副作用。如果assert具有更改任何变量的函数调用,则可能会影响结果,但如果它位于sizeof()中,则将确保调用不会实际发生。所有这些都表明,现在C++17解决了一个问题,C++20解决了另一个问题,这是正确的。
static_assert(sizeof([](int i){return i < 8;}) == 1);