#c #c 17 #circular-dependency #variant
#c #c 17 #циклическая зависимость #вариант
Вопрос:
Я пытаюсь справиться с циклической зависимостью в следующем сценарии:
У меня есть std:: variant, скажем:
//types.h
using Types = std::variant<int, double, std::string, SomeClass>;
SomeClass — довольно простая вещь, содержащая несколько указателей, с некоторой шаблонной логикой:
#someclass.h
class SomeClass {
// few simple members (pointers and an integer)
void use(Types arg); // note usage of Types here
template<typename T, typename Ts...> // implicitly assuming T == Ts... == Types
void use(T arg, Ts... tail) {
use(arg);
use(tail...);
}
SomeClass(const SomeClassamp;) = default; // works fine
};
Обычно я бы переадресовал SomeClass перед «использованием типов …», но это невозможно сделать, когда дело доходит до std:: variant. Я также на самом деле не нашел способа переадресовать директиву «using».
Одним из способов, который я нашел, было прямое объявление SomeClass и использование указателя на него в Types, но мне не нравится эта идея (SomeClass — действительно легкий объект с коротким сроком службы, я бы хотел сохранить его вне кучи).
Есть ли в C какой-либо другой способ (помимо указателей) решить эту проблему? У меня заканчиваются идеи.
Спасибо 🙂
Редактировать:
Проблема на самом деле появляется, только если я пытаюсь использовать типы до реального определения SomeClass, см. https://godbolt.org/z/4jzhEd
Комментарии:
1. С какой проблемой вы сталкиваетесь именно при использовании прямой передачи, объявленной
SomeClass
вstd::variant
?2. Не удается воспроизвести с помощью gcc . Компилируется просто отлично (после исправления очевидных опечаток и отсутствующих включений). Я не вижу проблемы с такого рода прямым объявлением. В чем бы ни заключалась ваша проблема, это должно быть что-то другое. Если вы используете другой компилятор, возможно, ошибка компилятора.
4. Мне удалось воспроизвести это godbolt.org/z/4jzhEd
5.Не имеет ничего общего с циклическими зависимостями или вариантами. Переместите определение
SomeStruct
послеSomeClass
. Вы просто не можете объявить член класса, тип которого не был определен.class B; class A { B b; }; class B {};
— это тоже не сработает по той же причине.
Ответ №1:
В приведенном вами живом примере все, что вам нужно для решения проблемы, — это определить SomeStruct
после SomeClass
.
Таким образом, ваш Types
вариант больше не будет иметь неполных типов при SomeStruct
определении. Другими словами, вот порядок:
class SomeClass;
using Types = std::variant<..., SomeClass>;
class SomeClass {
// ... // Types used here, but doesn't need to have all complete types
};
struct SomeStruct {
Types value;
// ...
};