У меня быстрый вопрос по поводу использования typedefs для длинных шаблонов.Суть: я оказался в чем-то вроде рассола - кажется, нет хорошего места для размещения typedef, кроме локальных для клиентских функций.Хотя есть похожие SO вопросы (см., Например, здесь ), ни один из них, похоже, не решает это точно.Обратите внимание, что этот вопрос не затрагивает вопрос о том, являются ли typedefs желательными в дальнейшем: я попытался упростить вещи для пояснения.
Моя проблема возникла при работе с boost::shared_ptr<T>
.По сути, я хочу сделать следующее:
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<Widget> WidgetPtr;
Размещение этого typedef в заголовке объявления Widget
кажется уродливым.Кажется, здесь есть два соображения: (i) если Widget
сам по себе не использует общие указатели в своих членах, мы добавили дополнительное включение (поскольку мы не можем переслать объявление класса шаблона boost::shared_ptr
-поправьте меня, если я ошибаюсь?) (ii) если мы хотим использовать этот typedef во время объявления другого класса (вызов этого класса Foo
), мы нарушаем лучшие практики, добавляя Widget.h
вместо простого объявления вперед Widget
или включительно WidgetFwd.h
... если только этот typedef не повторяется в последнем.Кроме того, кажется, не имеет смысла вводить определение boost::shared_ptr<Widget>
во время объявления самого Widget
- мы, кажется, смешиваем объявление Widget
с ожиданием того, как клиенты будут использовать интерфейс Widget
.
Ладно, это плохо, но это хуже: если я не попробую какую-либо комбинацию из вышеперечисленного, я получу дубликаты typedef в клиентском коде, что приводит к несогласованности (и, следовательно, вероятно, к ошибке)весь смысл в том, что с учетом Widget
, * typedef WidgetPtr
должен действовать как тип сам по себе.Пример: мы не хотим, чтобы Foo
использовал один WidgetPtr
, typedef равный boost::shared_ptr
, в то время как Bar
использует WidgetPtr в качестве typedef для std::auto_ptr
.
Другой метод (и один из немногих, о которых я упоминал в онлайн-обсуждении), - сделать typedef общедоступным членом Widget
, а затем использовать Widget::Ptr
:
class Widget {
// ...
public:
typedef boost::shared_ptr<Widget> Ptr;
};
Опять же, я некак, например, (i) это говорит о том, что тип указателя каким-то образом является членом класса, и (ii) это приводит к непростому интерфейсу.Что еще хуже: поскольку каждый класс, который я пишу, может указывать на использование умных указателей, я в конечном итоге гонюсь за хвостом воображаемого клиента.Гадкий, уродливый, уродливый.
В его нынешнем виде я удалил определения типов из этой кодовой базы (поскольку они привели к серьезной путанице, дублированию) и повторно ввел их локально в выбранные функции.Здесь опять есть проблема с непоследовательным использованием, но она не настолько серьезна.
Единственное другое решение, которое я могу придумать - и опять же, я не уверен, считается ли это хорошей практикой - это иметь утилитызаголовок, в который помещаются typedefs, потенциально в их собственном пространстве имен.В этот заголовок мы включили бы и покончим с этим.
Я что-то упускаю из виду или это просто сложно?
PS - Извинения за длину вышеупомянутого;Я не мог найти более простой способ полностью выразить проблему.