【发布时间】:2019-03-16 20:18:39
【问题描述】:
以下是我定义的宏的简化版本:
#define CHECK_EQ(a, b) do { if ((a) != (b)) abort(); } while (false)
这可行,但现在我想对评估的 a/b 值进行额外的工作,并且只想评估每个值一次。换句话说,类似于:
#define CHECK_EQ(a, b) \
do { \
const auto a_eval = (a); \
const auto b_eval = (b); \
if (a_eval != b_eval) { \
/* Print a_eval/b_eval */ \
abort(); \
} \
} while (false)
但这打破了一些当前的用途,例如触发-Wsign-compare CHECK_EQ(some_unsigned, 1)。我想要的是而不是auto 来确定比较的每一侧将转换为用于比较的类型。假设示例:
#define CHECK_EQ(a, b) \
do { \
using CmpType = CommonType<decltype(a), decltype(b)>::type; \ What goes here??
const CmpType a_eval = (a); \
const CmpType b_eval = (b); \
if (a_eval != b_eval) { \
/* Print a_eval & b_eval */ \
abort(); \
} \
} while (false)
我怀疑这也不完全正确,因为 decltype(1) 将是 int。有什么方法可以在不修改现有 CHECK_EQ 调用或禁止警告的情况下完成我想要的操作?
编辑:
关于应该和不应该返回警告的内容似乎有些混乱。当参数之一是正的 literal 时,使用 auto 会不必要地返回警告,这也是一个有效的无符号文本(但 auto 会导致 signed)。换句话说,理想情况下CHECK_EQ(a, b) 会产生警告当且仅当a == b 会。第二个最佳解决方案将允许混合类型,只要最终执行的比较是安全的 w.r.t.类型的签名。这似乎是使用std::common_type 完成的。
【问题讨论】:
-
您在寻找
std::common_type吗?或者decltype( a + b )? -
在这种情况下,警告对我来说似乎是有效的(也就是说,它警告调用代码存在合法的潜在问题)。您应该使用适当的转换来确保
a和b表达式在调用宏时是可比较的,而不是在宏本身内。
标签: c++ templates macros compiler-warnings