我有这样的情况:
#define FOO(Readonly) static_assert(Readonly, "Fire!");
Readonly
显然会直接粘贴为“false”或“true”,因此static_assert
将始终触发。如何编写条件代替Readonly
以使static_assert
正常工作?
这是我的预期用法:
#define CAT(x, y) CAT_(x, y)
#define CAT_(x, y) x ## y
#define GET_SET(Name, Readonly) decltype(Name) CAT(get, Name)() const { return Name; } \
void CAT(set, Name)(decltype(Name) value = decltype(Name)()) { \
static_assert( /* Insert Magic bullet here */ , #Name " is read-only."); \
Name = value; \
}
class Test
{
int x;
int y;
public:
GET_SET(x, false)
GET_SET(y, true)
};
示例预处理器输出:
decltype(x) getx() const { return x; } void setx(decltype(x) value = decltype(x)()) { static_assert(!false, "x" " is read-only."); x = value; }
decltype(y) gety() const { return y; } void sety(decltype(y) value = decltype(y)()) { static_assert(!true, "y" " is read-only."); y = value; }
答案 0 :(得分:5)
宏指令
#define FOO(Readonly) static_assert(Readonly, "Fire!");
正如你所猜测的那样,将转发传入Readonly的值,所以
FOO(false)
将生成
static_assert(false, "Fire!");
请记住static_assert
在条件为假时断言,这将始终触发。然而
FOO(true);
// generates
static_assert(true, "Fire!");
永远不会断言。
在您想要的输出中,您写道:
decltype(x) getx() const { return x; } void setx(decltype(x) value = decltype(x)()) { static_assert(!false, "x" " is read-only."); x = value; }
您似乎忘记了宏中的ReadOnly前面的!
。
static_assert
是一个编译时关键字,它在编译时检查,而不是运行时,所以除非有某些原因在模板实例化之前无法解析(例如,它正在检查模板类型的成员变量或模板参数)然后它总是在声明中失败。
以下代码似乎可以正常工作:
#define CAT(x, y) CAT_(x, y)
#define CAT_(x, y) x ## y
#define GET_SET(Name, Readonly) decltype(Name) CAT(get, Name)() const { return Name; } \
void CAT(set, Name)(decltype(Name) value = decltype(Name)()) { \
static_assert( !Readonly , #Name " is read-only."); \
Name = value; \
}
template<typename T>
class Foo
{
int x;
int y;
public:
Foo() : x(0), y(0) {}
GET_SET(x, false);
GET_SET(y, true);
};
当然,除了那个,因为我们使用static_assert
而不是运行时断言或抛出它,因此它会对坏情况进行限制。但它确实按照你的说法做了你想做的事。