Подтвердить что ты не робот

Что такое соглашение об именах при сопоставлении сложных карт STEP?

1) Что такое конвенция, используемая на практике, когда typedef'ing

что-то вроде

typedef std::map<SomeClass*, SomeOtherClass>  [SomeStandardName>]
typedef std::map<SomeClass*, std<SomeOtherClass> >  <[SomeStandardName]

2) Где вы обычно помещаете файлы заголовков typedef: глобально, локально для класса?

3) Вы вводите итераторы typedef или const map < > version?

4) Скажите, что у вас есть карта, используемая двумя разными понятиями, создаете ли вы два отдельных typedefs?

typedef map<string, SomeClass *> IDToSomeClassMap;
typedef map<string, SomeClass *> DescriptionToSomeClassMap;

Спасибо


Изменить # 1

Мне особенно интересны typedef STL-карты, такие как

typedef map<int, string> IdToDescriptionMap

или

typedef map<int, string> IdToDescription

Каковы распространенные практики?

4b9b3361

Ответ 1

Я предпочитаю следующее соглашение:

typedef std::map< Foo, Bar > FooToBarMap

Я намеренно избегаю typedef'ing итераторов, я предпочитаю явно ссылаться на них как:

FooToBarMap::const_iterator

Так как итераторы уже являются стандартными стандартными именами де-факто. И FooToBarMapConstIter на самом деле менее понятен для чтения, когда я просматриваю код, я нахожу.

Ответ 2

Об этих названиях нет общего правила. То, что я обычно делаю, это использовать имя класса "значение", приуроченное к Map. В вашем примере это будет SomeOtherClassMap. Я использую это соглашение, потому что обычно более интересно, что ваша карта содержит объекты "value" типа SomeOtherClass, а затем вы просматриваете их с помощью "ключей" SomeClass.

Ответ 3

Вторая часть вопроса - самая интересная для меня. Я предпочитаю помещать typedef в классы, которые их используют, когда есть логическое место для них, даже если они используются в других классах. Но это вызывает некоторые проблемы с форвардными объявлениями (которые мы используем для компиляции).

Например, в одном недавнем проекте у нас был класс с именем Io со встроенным typedef под названием Point, который сделал для очень читаемого кода - a Io::Point очень понятен и читабель. Но всякий раз, когда мы хотели использовать этот тип, мы должны были включать объявление класса Io, даже если бы все, что нам было нужно, было объявлением Io::Point, так как нет способа (который я знаю) переслать-объявить введите, что в классе, объявленном вперед.

В этом случае мы закончили работу в обоих направлениях. Мы создали глобальный тип IoPoint, а затем typedef d Io::Point к нему (чтобы наш уже написанный код не нужно было изменять). Не самый красивый ответ, но он выполнил свою работу.

Что касается других частей:

Мы не используем специальное соглашение для имен. Для карт мы часто используем * DescriptiveSomething *** Map ** (так как маловероятно, что мы когда-либо перейдем от карты к другому типу контейнера), но если DescriptiveSomething достаточно описательно и не конфликтует с существующим именем, мы часто будем использовать его вместо этого.

Обычно мы не пытаемся создать typedef для итераторов, так как легко (и очень легко читаем) просто использовать Type::iterator или Type::const_iterator. Тем не менее, мы иногда набираем их, если имя типа настолько длинное, что Type::const_iterator делает код слишком "коротким". (Не знаю лучшего способа сказать это, но вы, вероятно, знаете, что я имею в виду.)

Мы создаем разные typedef для каждой концепции, даже если два из них определяют точно такой же тип. Они могут меняться независимо друг от друга, поэтому для них разные имена типов упрощают последующий рефакторинг. Это также делает для более читаемого кода во многих случаях.

Ответ 4

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

  • Если typedef используется только в одном классе, добавьте typedef внутри определения класса
  • Если typedef используется несколькими несвязанными классами, добавьте его в файл заголовка на уровне области пространства имен

Что касается фактического имени типа typedef'd. Я называю это тем, что имеет смысл для typedef. Я не даю именам typedef какое-либо специальное соглашение, такое как префикс _t или что-то в этом направлении. Например

typedef stl::map<stl::string,Student> NameToStudentMap;

Ответ 5

Нет, просто имейте в виду общие правила для идентификаторов имен (без _ для начала и т.д.). Кроме того, если ваша организация имеет руководство по кодированию, лучше придерживаться ее.

Часто при определении собственного класса шаблона он становится беспорядочным без typedefs, поэтому я бы создал их там как удобные ярлыки. Однако, если это действительно куча классов, я бы предпочел иметь ее на уровне namespace.

Ответ 6

Мы используем следующее на моем рабочем месте:

typedef std::map WhateverMap;
typedef WhateverMap::iterator WhateverIter;
typedef WhateverMap::const_iterator WhateverCIter;

Что касается местоположения, это меняется. Если он специфичен для класса, он может быть в структуре Impl или может находиться в защищенных или частных областях объявления класса. Если он более общий (используется в файлах, используемых в API), мы помещаем его в отдельный заголовок стиля "FooTypes.h".

Обратите внимание, что, поскольку для нас обычно иногда изменять базовый тип, мы можем использовать "WhateverCollection" вместо "WhateverVec" или "WhateverList". Это не редкость, когда "WhateverList" фактически навязывается вектору или слайсту в зависимости от желаемых характеристик и характеристик производительности.

Ответ 7

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

typedef std::map< key, value > some_domain_specific_name_map;

или

typedef std::map< key, value > some_domain_specific_name_map_type;

также хорошая практика, чтобы сделать typedef для value_type или итераторов, обычно они имеют одно имя с именем map, но с завершением _value_type, _iterator.

Ответ 8

Обычно я определяю связанное имя с typedef, указывающим тип объекта.

Пример:

typedef std::vector<ClassCompStudent*> StudentCollection;

typedef std::map<std::string /*id*/, ClassCompStudent* /*pStudent*/>  IDToStudentMap;

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

class Test
{
public:
    typedef std::vector<ClassCompStudent*> StudentCollection;

    /* Users of Test need not know whether I use vector or list for 
        storing students. They get student collection and use it*/
    bool getStudents(StudentCollection& studentList) const;

    void print()
    {
        //do printing
    }
private:

    StudentCollection m_StudentList;
};

bool function(const Test& testObj)
{
    //If StudentCollection gets changed to list, this code need not be changed.
    StudentCollection aCollection;
    testObj.getStudents(aCollection);
    std::for_each(aCollection.begin(), aCollection.end(), std::mem_fun(&Test::print));
}

Ответ 9

Использование слова "Карта" или "Вектор" в виде бесполезной записи. Это слова, связанные с реализацией, а не с бизнес-моделью.

Вам не нужно показывать, что этот тип является вектором или картой. Вы можете использовать List. Как

typedef std::vector<std::string> List;
typedef std::set<std::string> List;

Это оба списка строк. И это правда.

typedef std::map<std::string, Object> List;
or  
typedef std::map<std::string, Object> NamedList;

Моя точка зрения не использует венгерскую нотацию.