循环constexpr
Cyclical constexpr
我想在 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 exceeded
和 expression did not evaluate to a constant
错误。
您可以将 x
和 y
隐藏在 class(或结构)中。即使您不想使用递归引用,出于信息封装的原因,这也是有益的:
#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 来检查。
我想在 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 exceeded
和 expression did not evaluate to a constant
错误。
您可以将 x
和 y
隐藏在 class(或结构)中。即使您不想使用递归引用,出于信息封装的原因,这也是有益的:
#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 来检查。