Я использую shared_ptr и STL экстенсивно в проекте, и это является ведущим к слишком долгим, подверженным ошибкам типам как shared_ptr< vector< shared_ptr<const Foo> > >
(Я - программист ObjC предпочтением, где длинные имена являются нормой, и все еще это слишком очень.) Это было бы намного более ясно, я верю, для последовательного вызова этого FooListPtr
и документируя соглашение о присвоении имен, которое означает "Ptr", shared_ptr и "Список" означают вектор shared_ptr.
Это легко к определению типа, но оно вызывает головные боли с заголовками. У меня, кажется, есть несколько опций того, где определить FooListPtr
:
Есть ли здесь лучшие практики? Как они складываются в реальном коде, когда возможность многократного использования, удобочитаемость и непротиворечивость являются главными?
Я отметил эту общественную Wiki, если другие хотят добавить дополнительные опции для обсуждения.
Я бы использовал комбинированный подход, состоящий из прямых заголовков и своего рода заголовка common.h
, специфичного для вашего проекта, и просто включает все заголовки форвардных деклараций и любые другие общие и легкие вещи.
Вы жалуетесь на накладные расходы, связанные с поддержанием вдвое большего количества заголовков, но я не думаю, что это должно быть слишком большой проблемой: прямым заголовкам обычно нужно знать только очень ограниченное количество типов (один?), И иногда даже не полный тип.
Вы даже можете попробовать автоматически сгенерировать заголовки с помощью сценария (это сделано, например, в SeqAn ), если на самом деле действительно столько заголовков.
+1 для документирования соглашений typedef.
Итак, вот предварительные предложения (измененные на основе того другого вопроса ..)
Заголовки стандартного типа
,
и т. Д.может перейти в предварительно скомпилированный заголовочный / общий включаемый файл для проекта. Это неплохо. (Я лично все еще включаю их там, где это необходимо, но это работает в дополнение к помещению их в PCH.)
Если контейнер является деталью реализации, определения типов идут туда, где объявлен контейнер (например, члены частного класса, если контейнер является частным членом класса)
Связанные типы (например, FooListPtr
) идут туда, где объявлен Foo, , если связанный тип является основным использованием типа. Это почти всегда верно для некоторых типов - например, shared_ptr
.
Если Foo
получает отдельный заголовок прямого объявления и связанный тип с этим согласен, он также перемещается в FooFwd.h.
Если тип связан только с определенным интерфейсом (например, параметр для общедоступного метода), он попадает туда.
Если тип является общим (и не соответствует ни одному из предыдущих критериев), он получает свой собственный заголовок. Обратите внимание, что это также означает включение всех зависимостей.
Мне это кажется «очевидным», но я согласен, что он не годится в качестве стандарта кодирования.
К сожалению, при использовании типизаторов вам придется выбирать между не самыми лучшими вариантами для ваших заголовочных файлов. Есть особые случаи, когда вариант один (прямо в заголовке класса) работает хорошо, но похоже, что вам он не подойдет. Есть также случаи, когда последний вариант работает хорошо, но обычно это происходит, когда вы используете подкласс для замены шаблона, включающего класс с единственным членом типа std::vector. В вашей ситуации я бы использовал решение с объявлением заголовка вперед. Это дополнительная типизация и накладные расходы, но иначе это не был бы C++, верно? Это сохраняет вещи раздельными, чистыми и быстрыми.