I am looking for naming conventions for typedef of lengthy collections definitions. We have some c++ code which used auto
to get away with style murder, but we need to make this code compiling on a non c++11 compiler. We are looking to establish a convention for typedef
of collections, which can become quite lengthy
For instance
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
There are so many nuances (iterator
before t
than at beginning, using type rather than t, ditching the prefix map
, etc...) that half of the time you select one nuance, half of the time you select the other.
At the end no typedef look like the other.
答案 0 :(得分:2)
typedef std::map<enum MyFirstEnum,enum MySecondEnum> map_enum2_by_enum1_t;
如果没有更好地描述映射的“大图”名称,那么我建议Enum2_By_Enum1
或Enum1_To_Enum2
:两者都暗示没有map
位的关联容器,这是我的品味有点Hungarian,但有相同的缺陷(例如,如果你移动说unordered_map
,你会改变吗 - 如果你还记得 - 或者让它误导?)。
typedef map_enum2_by_enum1_t::value_type vtype_map_enum2_by_enum1_t;
我无法想象这有用......当具体值类型未知时(例如地图或值类型为1),我通常只在模板内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获得了改进代码的具体示例,请分享。
答案 1 :(得分:1)
这一切显然都是主观的。也就是说,我倾向于使用命名空间来分隔/隔离类型,并保持名称小/短:
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();
// ...
}
答案 2 :(得分:0)
有各种各样的方式。
通常,我的目标是从一开始就避免这个问题,方法是从顶层设计中导出类型名,而不是从用于实现它的类型中导出。从顶层的角度来看,通常存在一种类型所代表的概念,而这个概念通常是一个合适的名称 - 就在早期设计中。将类型名称等内容改造为现有的草率代码确实是一个坏主意。
但是,鉴于这是你的出发点,我建议不要过于奢侈地装饰这些名字并做这样的事情。
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
确定所有范围。
如果您的风格指南允许或要求,可以通过使用驼峰式案例来避免使用下划线(例如,而不是map_first_second_iterator
使用MapFirstSecondIterator
。对于开发人员来说,关键在于使用您的命名约定而不是过于复杂,而不是完美的。