Шаблон взаимозависимости - PullRequest
3 голосов
/ 10 марта 2010

шаблон структура А { typedef float atype; typedef имя типа tB :: btype typeB; }; шаблон структура B { typedef float btype; typedef имя типа tA :: atype typeA; }; * * Тысяча одна

struct MyB;
struct MyA: public A<MyB>{};
struct MyB: public B<MyA>{};

int main(int argc, char *argv[])
{
}

не компилируется, потому что "main.cpp: 6: ошибка: неверное использование неполного типа" struct MyB ’".

В основном, компилятор не может решить цикл, потому что определение A зависит от определения B наоборот. Есть ли способ разобраться с этим? спасибо,

Ответы [ 3 ]

3 голосов
/ 10 марта 2010

Это не может быть решено напрямую. Вчера был очень похожий вопрос (хотя и не включающий шаблоны): C ++: Как можно избежать «недопустимого ковариантного возвращаемого типа» в унаследованных классах без приведения?

Вы можете перестроить свои решения таким образом, чтобы эта взаимозависимость больше не требовалась, или перестроить свое решение так, что вы используете параметры шаблона только для объявления ссылок и указателей (поскольку их объявления не требуют, чтобы полное определение типа доступно в данный момент).

1 голос
/ 10 марта 2010

Если вы избавляетесь от шаблона дымовой завесы, то, что у вас есть, включает бесконечную рекурсию. На данный момент, подумайте о наследовании как о немного ином способе определения содержания (что это такое). Вы говорите, что myA содержит myB, который, в свою очередь, содержит myA, который, в свою очередь, содержит myB и т. Д. Навсегда - то есть любой отдельный объект любого типа имеет бесконечный размер ...

Редактировать: как указано в litb, ни одна из этих структур не содержит ничего, поэтому теоретически они не занимают места (благодаря пустой оптимизации базового класса). Хотя это правда, что это может помешать структурам самим иметь бесконечный размер, AST, который должен сгенерировать компилятор для любого из них, все еще бесконечен - например, myA :: myB :: myA :: myB :: myA :: myB :: myA :: myB ... myB :: btype (конечный элемент myA::atype, myA::tA или myB::tB) является допустимым именем типа для любого уровня вложенности. По крайней мере, как обычно пишется компилятор, в AST не допускаются циклы, оставляя бесконечное AST единственной альтернативой.

1 голос
/ 10 марта 2010

Я думаю, что, поскольку вы используете определение типа tB :: btype, компилятору нужно знать структуру типов MyB, чего нет (вы только это объявили).Вы можете проверить это: на самом деле, если вы закомментируете ссылку на tA :: atype в struct B, вы все равно получите ту же ошибку, в то время как если вы закомментируете typedef typeB в struct A, компилятор не будет жаловаться.

Если оставить в стороне, вы уверены, что вам нужна такая круговая зависимость?

...