typedef 标准集合时的命名约定

naming convention when typedef standard collections

我正在寻找冗长集合定义的 typedef 的命名约定。我们有一些使用 auto 来逃避风格谋杀的 c++ 代码,但我们需要让这段代码在非 c++11 编译器上编译。我们正在寻求为 typedef 集合建立一个约定,这可能会变得相当冗长

例如

typedef std::map<enum MyFirstEnum,enum MySecondEnum> map_enum2_by_enum1_t
typedef map_enum2_by_enum1_t::value_type             vtype_map_enum2_by_enum1_t
typedef map_enum2_by_enum1_t::iterator               map_iterator_enum2_by_enum1_t

有很多细微差别(iteratort 之前而不是开始,使用类型而不是 t,放弃前缀 map,等等...)一半一次你 select 一个细微差别,一半时间你 select 另一个。 最后没有 typedef 看起来像另一个。

有各种各样的方法。

通常,我的目标是从一开始就避免这个问题,方法是从顶层设计而不是从用于实现它的类型中派生类型名称。从顶层的角度来看,类型通常代表一些概念,并且该概念通常是一个合适的名称——就在早期设计中。将类型名称之类的东西改造到现有的草率代码上确实是个坏主意。

但是,鉴于这是你的出发点,我建议不要过于奢侈地装饰名字并做这样的事情。

namespace <libname>_Type
{
      typedef std::map<FirstEnum, SecondEnum> map_first_second;
      typedef map_first_second::value_type map_first_second_value;
      typedef map_first_second::iterator map_first_second_iterator;
      typedef map_first_second::const_iterator map_first_second_const_iterator;

}

或(如果您的库有自己的命名空间)

namespace <libname>
{
     namespace Type
     {
          typedef std::map<FirstEnum, SecondEnum> map_first_second;
          typedef map_first_second::value_type map_first_second_value;
          typedef map_first_second::iterator map_first_second_iterator;
          typedef map_first_second::const_iterator map_first_second_const_iterator;

     }
}

现在,好吧,使用命名空间可能意味着需要做更多的设置工作,但使用类型更容易。

for (<libname>::Type::map_first_second_iterator i, end = some_map.end();
      i != end;
      ++i)
{
   do_something(i);
}

这可以简化,以避免所有范围界定明智 using

如果您的风格指南允许或要求,则可以通过使用驼峰式大小写来避免使用下划线(例如,使用 [=15= 而不是 map_first_second_iterator)。对于开发人员而言,关键在于始终如一地使用您的命名约定,不要过于复杂,而不是拥有一个完美的命名约定。

typedef std::map<enum MyFirstEnum,enum MySecondEnum> map_enum2_by_enum1_t;

如果没有 "big picture" 名称可以更好地描述映射,那么我建议使用 Enum2_By_Enum1Enum1_To_Enum2:两者都表示没有 map 位的关联容器,这对我来说有点太 Hungarian 了,但有同样的缺陷(例如,如果你说 unordered_map 你会改变它 - 如果你记得 - 还是让它产生误导?)。 =27=]

typedef map_enum2_by_enum1_t::value_type             vtype_map_enum2_by_enum1_t;

我无法想象这有什么用...当具体值类型未知(例如地图或值类型)时,我通常只会 typedef 模板中的地图 value_type是模板参数之一)并且地图没有特殊或排他性意义,因此其 value_type 可以合理地 typedef 编辑为 模板的 value_type,在那种情况下,映射必然有一些其他更高级别的名称来反映它在模板实例化中的作用。

总而言之,如果可能的话我会省略这个并直接使用 enum2/MyFirstEnum

typedef map_enum2_by_enum1_t::iterator               map_iterator_enum2_by_enum1_t;

没有理由这样做,除非 typedef 标识符比它的别名短得多。只需使用 <mapname>::iterator.

如果您认为您有通过最后两个 typedef 得到改进的具体代码示例,请分享它。

这一切显然是主观的。也就是说,我倾向于对 separate/isolate 类型使用命名空间,并保留名称 small/short:

enum foo_result;
enum bar_state;
enum baz_values;

namespace mappings { // namespace name tells you what's inside, so there is
                     // no need to call names inside with "map_" prefix

    // "associate foo_result to bar_state"
    typedef std::map<foo_result,bar_state> foo_result2bar_state;

    // "associate foo_result to baz_values"
    typedef std::map<foo_result,baz_values> foo_result2baz_values;

    // I would not define these here:
    // typedef foo_result2bar_state::value_type
    //    foo_result2bar_state_value_type;
}

然后客户端代码变成自我描述:

void f(mappings::foo_result2bar_state& m) // foo_result2bar_state is a "mapping" of types
{
    // I prefer to have this alias in client code (i.e. where I use it)
    typedef mappings::foo_result2bar_state::iterator itr;

    itr begin = m.begin();
    // ...
}