Структура, содержащая ссылки на себя ИЛИ другой тип структуры?

Я хочу использовать структуры для создания типа данных, который содержит другие ссылки на массив самой структуры ИЛИ структуры другого типа. Использование шаблонов, очевидно, приведет к бесконечному объявлению самого типа, когда ссылка относится к тому же универсальному типу. Мое текущее решение состоит в том, чтобы явно объявить другой тип структуры и тип самой структуры. Мне было интересно, есть ли более умное решение (с использованием структур).

struct Transform
{
    float x;
    float y;
    float z;
    float qx;
    float qy;
    float qz;
    float qw;
};

struct Pattern
{
    enum type{ linear, rectangular, circular };
    char name[20];
    int id;
    Transform t[PATTERN_SIZE];
};

struct Group
{
    enum type{ pattern, group };
    char name[20;
    int id;
    Group *g[20];
    Pattern *p[20];
};

Нет, это не дубликат этого вопроса. Я спрашиваю, возможно ли иметь переменную внутри структуры либо самого типа, либо шаблона типа.

Ruptr 20.05.2019 13:05

Ок, вопрос сформулирован странно. Тогда то, что вы ищете, это std::variant (или boost::variant или подобное, если вы используете более старый компилятор).

Dan M. 20.05.2019 13:08

Ваш вопрос очень плохо сформулирован. Не могли бы вы объяснить, какую проблему вы пытаетесь решить? Это выглядит как проблема XY в опубликованном виде.

Daniel Langr 20.05.2019 13:41

Как вы понимаете, что союз является расточительным? Если пути кода когда-либо понадобится A, в нем должно быть место для A, поэтому, если ваш обычный путь не B, а B значительно меньше, любая полиморфная схема, которая включает операцию выделения и/или указатель, вероятно, будет в целом более «расточительной». ", особенно когда вам нужен A.

Gem Taylor 20.05.2019 17:45

@GemTaylor Возможно, ты прав. Я предполагаю, что это своего рода ранняя чрезмерная оптимизация, но я еще не очень хорошо знаком с C++, поэтому я просто пытаюсь понять возможности языка. В любом случае, спасибо за комментарии. P.S. извиняюсь за некорректно сформулированный вопрос :/

Ruptr 20.05.2019 22:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
466
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если вы хотите иметь переменную типа A или B (или C...), вы можете использовать тип станд::вариант, который был введен в C++17, или его собственные реализации, если ваш компилятор его не поддерживает. Этот — вот как это может выглядеть. Для простых случаев вы также можете сделать это вручную, используя союзы, хотя предпочтительнее библиотечное решение. Если вам нужно специальное решение для объединения/структуры, я предлагаю вам направить свой вопрос в C, а не C++.

Однако похоже, что вы пытаетесь создать какую-то древовидную структуру. Я обнаружил, что для таких структур в C++ лучше всего работает простое наследование.

std::variant допускает неполные типы?

463035818_is_not_a_number 20.05.2019 13:26

Я только что проверил, это не так :\

hegel5000 20.05.2019 13:27

@formerlyknownas_463035818 разрешает указатели на неполные типы, о чем и был вопрос.

Dan M. 20.05.2019 13:31

@formerlyknownas_463035818 это плохо сформулировано. В приведенном примере используются указатели и говорится о самой структуре, а не об использовании буквальных ссылок C++. Ссылки на С++ не имеют смысла, например, если вы не можете создать их массив. См. комментарий автора к его вопросу: I am asking if it is possible to have a variable within the struct be of either type itself or type pattern.

Dan M. 20.05.2019 13:37

а, извините, понял ;). Раньше я не слишком внимательно читал код OP. Тем не менее, мой комментарий остается в силе: в вашем вопросе не упоминается, что у вас не может быть std::variant незавершенных типов, но вы должны использовать указатели (и тогда я все еще не понимаю, какой смысл использовать std::variant в первую очередь, но это, вероятно, просто мое недоумение)

463035818_is_not_a_number 20.05.2019 13:38

Я бы не стал отвечать на вопросы с пометкой C++11 решением, для которого требуется C++17. (Или сначала вы можете спросить OP в комментариях о доступности C++ 17).

Daniel Langr 20.05.2019 13:44

@DanielLangr, как я писал в ответе, есть реализации C++ 11, доступные в boost и других библиотеках.

Dan M. 20.05.2019 13:48

@formerlyknownas_463035818 Что ж, в ответах на прямой вопрос «возможно ли, чтобы переменная в структуре имела либо сам тип, либо шаблон типа». Хотя кажется, что автор вопроса пытается реализовать древовидную структуру, для которой что-то вроде простого наследования было бы более чистым решением.

Dan M. 20.05.2019 13:49

@ДэнМ. Является ли наследование когда-либо действительно чистым :)

Ruptr 20.05.2019 22:49

Хотя я пометил как C++11, я благодарен за предложения std::variant. Спасибо

Ruptr 20.05.2019 22:50
Ответ принят как подходящий

Это действительно C-ish, но пока вам нужны только указатели, void * — это многоцелевой указатель:

struct Group
{
    enum type{ pattern, group } t;
    char name[20];
    int id;
    void *children[20];    // cast elements to `Group *` or `Pattern *` depending on t
};

Однако состав Group **/Pattern ** формально не определен.

Quentin 20.05.2019 13:58

@Quentin: Да, правильный способ - преобразовать отдельные элементы массива соответственно в Group * или Pattern *. Мне было лень заботиться о деталях, потому что это настолько C-ish, что я опубликовал его только для полноты возможных решений. Но вы поняли ;-). Я отредактировал свой пост.

Serge Ballesta 20.05.2019 14:30

C-ish на самом деле положительный для меня, так что спасибо за простое, но полезное предложение

Ruptr 20.05.2019 22:53

Кстати, если вам нужен подход, ориентированный на C, вы можете прочитать о методе Союз с тегами (который в основном реализует std::variant).

Dan M. 20.05.2019 23:21

@ДэнМ. Спасибо чувак.

Ruptr 20.05.2019 23:28

Другие вопросы по теме