在宏中使用static_assert

时间:2014-01-27 03:38:52

标签: c++ c++11

我有这样的情况:

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

Live Example

1 个答案:

答案 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);
};

http://ideone.com/BkRYBE

当然,除了那个,因为我们使用static_assert而不是运行时断言或抛出它,因此它会对坏情况进行限制。但它确实按照你的说法做了你想做的事。