Я хочу использовать структуры для создания типа данных, который содержит другие ссылки на массив самой структуры ИЛИ структуры другого типа. Использование шаблонов, очевидно, приведет к бесконечному объявлению самого типа, когда ссылка относится к тому же универсальному типу. Мое текущее решение состоит в том, чтобы явно объявить другой тип структуры и тип самой структуры. Мне было интересно, есть ли более умное решение (с использованием структур).
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];
};
Ок, вопрос сформулирован странно. Тогда то, что вы ищете, это std::variant (или boost::variant или подобное, если вы используете более старый компилятор).
Ваш вопрос очень плохо сформулирован. Не могли бы вы объяснить, какую проблему вы пытаетесь решить? Это выглядит как проблема XY в опубликованном виде.
Как вы понимаете, что союз является расточительным? Если пути кода когда-либо понадобится A, в нем должно быть место для A, поэтому, если ваш обычный путь не B, а B значительно меньше, любая полиморфная схема, которая включает операцию выделения и/или указатель, вероятно, будет в целом более «расточительной». ", особенно когда вам нужен A.
@GemTaylor Возможно, ты прав. Я предполагаю, что это своего рода ранняя чрезмерная оптимизация, но я еще не очень хорошо знаком с C++, поэтому я просто пытаюсь понять возможности языка. В любом случае, спасибо за комментарии. P.S. извиняюсь за некорректно сформулированный вопрос :/





Если вы хотите иметь переменную типа A или B (или C...), вы можете использовать тип станд::вариант, который был введен в C++17, или его собственные реализации, если ваш компилятор его не поддерживает. Этот — вот как это может выглядеть.
Для простых случаев вы также можете сделать это вручную, используя союзы, хотя предпочтительнее библиотечное решение. Если вам нужно специальное решение для объединения/структуры, я предлагаю вам направить свой вопрос в C, а не C++.
Однако похоже, что вы пытаетесь создать какую-то древовидную структуру. Я обнаружил, что для таких структур в C++ лучше всего работает простое наследование.
std::variant допускает неполные типы?
Я только что проверил, это не так :\
@formerlyknownas_463035818 разрешает указатели на неполные типы, о чем и был вопрос.
@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.
а, извините, понял ;). Раньше я не слишком внимательно читал код OP. Тем не менее, мой комментарий остается в силе: в вашем вопросе не упоминается, что у вас не может быть std::variant незавершенных типов, но вы должны использовать указатели (и тогда я все еще не понимаю, какой смысл использовать std::variant в первую очередь, но это, вероятно, просто мое недоумение)
Я бы не стал отвечать на вопросы с пометкой C++11 решением, для которого требуется C++17. (Или сначала вы можете спросить OP в комментариях о доступности C++ 17).
@DanielLangr, как я писал в ответе, есть реализации C++ 11, доступные в boost и других библиотеках.
@formerlyknownas_463035818 Что ж, в ответах на прямой вопрос «возможно ли, чтобы переменная в структуре имела либо сам тип, либо шаблон типа». Хотя кажется, что автор вопроса пытается реализовать древовидную структуру, для которой что-то вроде простого наследования было бы более чистым решением.
@ДэнМ. Является ли наследование когда-либо действительно чистым :)
Хотя я пометил как C++11, я благодарен за предложения std::variant. Спасибо
Это действительно 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: Да, правильный способ - преобразовать отдельные элементы массива соответственно в Group * или Pattern *. Мне было лень заботиться о деталях, потому что это настолько C-ish, что я опубликовал его только для полноты возможных решений. Но вы поняли ;-). Я отредактировал свой пост.
C-ish на самом деле положительный для меня, так что спасибо за простое, но полезное предложение
Кстати, если вам нужен подход, ориентированный на C, вы можете прочитать о методе Союз с тегами (который в основном реализует std::variant).
@ДэнМ. Спасибо чувак.
Нет, это не дубликат этого вопроса. Я спрашиваю, возможно ли иметь переменную внутри структуры либо самого типа, либо шаблона типа.