Само- / циркулярная ссылка в выражениях «использование» - PullRequest
7 голосов
/ 07 октября 2019

Я попытался определить тип варианта для динамических переменных в моей программе, но я не могу заставить его хранить функцию, которая возвращает его как тип.

using Value = std::variant<Integer, Float, Function>;
using Function = std::function<Value()>;

Этоне будет компилироваться, потому что Function должен быть определен в то время, когда Value есть, но Function зависит также от Value. Я попытался исправить это, вставив тип Function в список шаблонов вариантов, но кажется, что операторы using не могут ссылаться на себя или объявляться вперед.

Мое лучшее решение до сих пор определялоFunction как структура, чтобы я мог ее объявить. Это работает, но выглядит так глупо, поэтому мне интересно, есть ли лучший способ?

struct Function;
// define Value
struct Function : std::function<Value()> {};

Для пояснения, std::function использовался как часть примера, потому что я думал, что будет проще показатьчто я пытался сделать, и это также было необходимо для моего хакерского решения. Я бы предпочел, чтобы это работало с обычными указателями на функции, если это возможно.

1 Ответ

3 голосов
/ 07 октября 2019

Это не может работать, потому что вы, по сути, пытаетесь создать это:

std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<std::variant<Integer, Float, std::function<...()>>()>>()>>()>>()>>()>>()>>()>>()>>()>>()>>;

Таким образом, в сущности, у вас есть бесконечная рекурсия внутри объявлений типов.

Вам нужно обойти это, используя какой-то тип, который не имеет рекурсивного определения, но использование перенаправленного struct, как вы предлагаете, не является опцией, поскольку std::variant допускает только полные типы.

Что вы можете сделать, так это объявить struct, а затем использовать контейнер / упаковщик / умный указатель по вашему выбору (например, std::unique_ptr<Function>) в вашем std::variant:

struct Function;
using Value = std::variant<Integer, Float, std::unique_ptr<Function>>;
struct Function : std::function<Value()> {};
...