在宏中使用static_assert

Using a static_assert in a macro

本文关键字:static assert      更新时间:2023-10-16

我有这样的情况:

#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; }

实时示例

宏指令

#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);
};

http://ideone.com/bkrybe

当然,除非它在坏案例上进行了禁止,因为我们已经使用了static_assert而不是运行时断言或投掷。但这做了您所说的您想要做的事情。