周期性的constexpr

时间:2017-05-14 21:06:27

标签: c++ c++11 cyclic-reference

我想在C ++中使用constexpr构建一些状态机,这要求状态及其转换也是constexpr。如果状态机具有循环部分(例如,状态1具有到状态2的转换,并且状态2具有到状态1的转换),则需要循环的constexpr。但是,如下所示的代码不能编译(MSVC 2017),因为constexpr必须在声明时初始化:

class a
{
public:
    constexpr a(a const & v) : v(v) {}
    a const & v;
};

constexpr extern a x;
constexpr a y = a(x);
constexpr a x = a(y);

是否有解决方法或计划在未来的C ++标准版本中解决这个问题?

编辑:根据erenon的评论,我尝试了这个:

class a
{
public:
    constexpr a(a const & v) : v(v) {}
    a const & v;
};

constexpr a x_getter();

constexpr a y_getter() {
    return a(x_getter());
}

constexpr a x_getter() {
    return a(y_getter());
}

constexpr a test = x_getter();

但它失败并显示一条有趣的警告消息:最后一行出现Warning C4591 'constexpr' call-depth limit of 512 exceededexpression did not evaluate to a constant错误。

1 个答案:

答案 0 :(得分:3)

您可以在类(或结构)中隐藏xy。即使你不想有递归引用,这对于信息封装的原因也是有益的:

#include <iostream>

class a
{
public:
    // use `a const *` to avoid overriding default copy-constructor
    constexpr a(a const *v_) : v(*v_) {}
    a const & v;
};

struct state_machine
{
    a const x,y;
    constexpr state_machine() : x(&y), y(&x) {}
private:
    // can't copy or move a state_machine (this implicitly deletes operator=):
    state_machine(state_machine&&) = delete;
};

constexpr state_machine sm;

int main(int argc, char **argv) {
    std::cout << "&x: " << &sm.x << ", &x.v: " << &sm.x.v << '\n';
    std::cout << "&y: " << &sm.y << ", &y.v: " << &sm.y.v << '\n';
    // state_machine sm2{sm}; // forbidden
}

上面的代码使用-std=c++11-std=c++14使用g ++版本5.4.1和6.2.0进行了测试。我没有MSVC来检查。