У меня есть быстрый вопрос относительно использования typedef для длинных шаблонов. Суть: я нашел себя в чем-то рассол - там, похоже, не место для размещения typedefs, кроме локальных для клиентских функций. Хотя есть похожие вопросы SO (см. здесь), ничто, кажется, не обращается к этому точно. Обратите внимание, что в этом вопросе не рассматривается вопрос о том, желательны ли typedefs в дальнейшем: я попытался упростить вещи для пояснительных целей.
Моя проблема возникла при работе с boost::shared_ptr<T>
. В принципе, я хочу сделать следующее:
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<Widget> WidgetPtr;
Размещение этого typedef в заголовке объявления Widget
кажется уродливым. Здесь, по-видимому, есть два соображения: (i) если Widget
сам не использует общие указатели в своих членах, мы добавили дополнительный include (поскольку мы не можем переслать объявление boost::shared_ptr
template class- исправьте меня, если я ошибаюсь?) (ii) если мы хотим использовать этот typedef во время объявления другого класса (вызов этого класса Foo
), мы нарушаем лучшие практики, включая Widget.h
вместо простого переадресации объявления Widget
или включая WidgetFwd.h
... если этот typedef не дублируется в последнем. Кроме того, во время объявления самой Widget
не имеет смысла вводить typedef boost::shared_ptr<Widget>
- мы, кажется, смешиваем объявление Widget
с ожиданием того, как клиенты будут использовать интерфейс Widget
.
Хорошо, так плохо, но это хуже: если я не пытаюсь выполнить какую-либо комбинацию выше, я получаю дубликат typedefs в клиентском коде, что приводит к несогласованности (и, следовательно, скорее всего, к ошибке) - весь смысл что при задании Widget
a WidgetPtr
typedef должен действовать как тип в своем собственном праве. Пример: мы не хотим, чтобы 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) он приводит к неустойчивому интерфейсу. Хуже того: поскольку каждый класс, который я пишу, потенциально можно указать на использование интеллектуальных указателей, я в конечном итоге преследую воображаемый клиентский хвост. Уродливый, уродливый, уродливый.
Как бы то ни было, я удалил typedef из этой кодовой базы (поскольку они привели к серьезной путанице, дублированию) и повторно представили их локально в выбранных функциях. Здесь снова возникает проблема с непоследовательным использованием, но это не так уж тяжело.
Единственное другое решение, о котором я могу думать, - и снова я не уверен, считается ли это хорошей практикой, - это иметь заголовок утилиты, в который помещаются typedefs, потенциально в их собственном пространстве имен. В этом заголовке мы будем включать и делать с ним.
Я пропустил что-то очевидное или это просто сложно?
PS - Извинения за длину выше; Я не мог найти более простой способ полностью выразить проблему.