Каково ваше соглашение для typedef'ing shared_ptr? - PullRequest
45 голосов
/ 27 апреля 2010

Я переключаюсь между соглашениями об именах для определения типа шаблона boost :: shared_ptr. Например:

typedef boost::shared_ptr<Foo> FooPtr;

Прежде чем остановиться на соглашении, я бы хотел посмотреть, что используют другие. Каково ваше соглашение?

EDIT:

Для тех, кто вкладывает typedef в Foo, вас не беспокоит, что Foo теперь "знает", как он будет передаваться? Кажется, нарушить инкапсуляцию. Как насчет этого:

class Foo
{
public:
    typedef std::vector<Foo> Vector
};

Вы не сделали бы это сейчас, не так ли? : -)

Ответы [ 16 ]

28 голосов
/ 20 июня 2017

Я бы тоже хотел добавить некоторые опции к этому старому вопросу, хотя они могут быть весьма спорными ...

Аналогично Ответ OldPeculier Мне нравятся короткие имена типов, максимально приближенные к стандартным указателям.

В проекте, который использовал shared_pointer почти везде, я использовал

typedef boost::shared_ptr<Foo> Foo_;

// usage examples:
Foo* myFoo0;
Foo_ myFoo1;

Я воспользовался тремя вещами:

  1. То, что символ подчеркивания каким-то образом выглядит как оператор, но обрабатывается в основном как буква, так что он может быть частью идентификатора (и я вижу нет правила, запрещающего его в конце идентификатора ).
  2. Что мне нужно было только придумать one typedef.
  3. Я предпочитаю Foo* myFoo1; над Foo *myFoo1; по нескольким причинам, и он отлично сочетается с Foo_ myFoo2.

Когда мне нужны typedef для разных видов умных указателей, я бы выбрал

typedef shared_ptr<Foo> Foo_S;
typedef weak_ptr<Foo>   Foo_W;
typedef unique_ptr<Foo> Foo_U;

// usage examples:
Foo*  myFoo2;
Foo_S myFoo3;
Foo_W myFoo4;
Foo_U myFoo5;

С увеличением поддержки Unicode в стандартах и ​​реализациях компилятора у меня возникнет соблазн попробовать следующий синтаксис, предполагая, что эти символы звездочки будут рассматриваться как обычная часть идентификатора типа. Конечно, это практично, только если у всех заинтересованных разработчиков есть удобный метод ввода текста:

typedef shared_ptr<Foo> Foo★;
typedef weak_ptr<Foo>   Foo☆;
typedef unique_ptr<Foo> Foo✪;

// usage examples:
Foo* myFoo6;
Foo★ myFoo7;
Foo☆ myFoo8;
Foo✪ myFoo9;

(Быстрый тест показал, что это на самом деле не работает, по крайней мере, с моей средой сборки. Но то же самое верно для Foo_ä.)

26 голосов
/ 27 апреля 2010

Ответ: не делай этого. Это удобно для вас и больше ни для кого. Скажи, что ты имеешь в виду.

15 голосов
/ 27 апреля 2010

Мои предпочтения:

class Foo
{
public:

    typedef boost::shared_ptr<Foo> SharedPointer;
};

Проблема только с FooPtr заключается в том, что у вас могут быть разные типы указателей (например, weak_ptr с). Я также не очень люблю аббревиатуры, но это совсем другое дело.

5 голосов
/ 27 апреля 2010

Лично в коде, за который я отвечаю, вы обычно видите определение типа FooPtr в той же области имен, что и Foo и Foo будет содержать обобщенное определение типа 'SmartPtr' для тот же тип, что и FooPtr. Наличие FooPtr позволяет легко и без подробного ручного использования. наличие вложенной typedef для 'SmartPtr' или некоторого эквивалента позволяет легко использовать универсальные шаблоны, макросы и т. д., не зная фактического типа интеллектуального указателя.

Кроме того, я бы предложил добавить к этому вопросу «субъективный» тег.

4 голосов
/ 27 апреля 2010

Я использовал как внешний, так и инкапсулированный typedef, но в итоге получил первое,

typedef boost::shared_ptr<Foo> FooPtr; 

только потому, что в комбинированных выражениях это выглядит чище, чем Foo::Ptr.

Вас не беспокоит, что Фу теперь "осознает", как это будет передаваться?

Достаточно часто эти классы создаются только фабричным методом:

struct Foo
{
     static FooPtr Create() { return FooPtr(new Foo); }

   protected:
     Foo() {}
}

Это вроде "сильнее", чем инкапсуляция typedef, но это очень распространенный шаблон.

2 голосов
/ 21 октября 2011

Я вообще не фанат очень коротких идентификаторов, но это один из случаев, когда я буду их использовать.

class Foo
{
public:
    typedef std::shared_ptr<Foo> p;
};

Это позволяет shared_ptr напоминать обычные указатели настолько близко, насколько это возможно, без риска путаницы.

Foo* myFoo;
Foo::p myFoo;

А что касается нарушения инкапсуляции - нет, определение типа тип shared_ptr внутри класса не нарушает инкапсуляцию, как определение типа вне класса. Какой смысл "инкапсуляции" это нарушит? Вы не раскрываете ничего о реализации Foo. Вы просто определяете тип. Это совершенно аналогично отношениям между Foo * и Foo. Foo * - это определенный тип указателя на Foo (по умолчанию). Foo :: p - другой тип указателя на Foo. Вы не нарушаете инкапсуляцию, вы просто добавляете систему типов.

2 голосов
/ 27 апреля 2010

Я обычно инкапсулирую typedef внутри класса. Причина в том, что у нас есть некоторый код, чувствительный к памяти, и он позволяет легко переключаться между boost::shared_ptr и boost::intrusive_ptr Поскольку intrusive_ptr - это то, что класс должен поддерживать, для меня имеет смысл иметь представление о том, какой разделяемый указатель будет использоваться в классе.

2 голосов
/ 27 апреля 2010

Я не большой поклонник венгерских соглашений об именах, я обычно использую:

typedef boost::shared_ptr<Foo> FooSharedPtr;

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

1 голос
/ 01 апреля 2015
  typedef shared_ptr<Foo> sptr_Foo;
  typedef weak_ptr<Foo>   wptr_Foo;
  typedef unique_ptr<Foo> uptr_Foo;
1 голос
/ 27 апреля 2010

Мой первый ответ - спросить: «Почему это так?»

В ответ на ваше редактирование: На самом деле это довольно интересный подход, который может быть полезен во многих ситуациях. С его помощью вы можете вернуться к исходному вопросу:


struct object
{
  typedef object* ptr_t;
  typedef shared_ptr<object> shared_ptr_t;
  typedef weak_ptr<object> weak_ptr_t;
  typedef unique_ptr<object> unique_ptr_t;
  etc...
}
...