Циклическое constexpr
Я хотел бы построить некоторые машины состояний, используя constexpr в C++, который требует, чтобы состояния и их переходы также были constexpr. Если государственная машина имеет циклическую часть (напр. состояние 1 переходит в состояние 2 и состояние 2 переход в состояние 1), то требуется цикличность таких является. Однако код, подобный приведенному ниже, не компилируется (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++?
Edit: основываясь на комментарии эренона, я попытался сделать следующее:
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
ошибки в последней строке.
1 ответ:
Можно скрыть
x
иy
внутри класса (или структуры). Даже если вы не хотите иметь рекурсивные ссылки, это было бы полезно по причинам инкапсуляции информации:Приведенный выше код был протестирован с версиями g++ 5.4.1 и 6.2.0 с использованием#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
. У меня нет MSVC, чтобы проверить это.