【问题标题】:Should names representing template types be a single character?代表模板类型的名称应该是单个字符吗?
【发布时间】:2010-11-11 08:34:34
【问题描述】:

我们正在根据these guidelines 定义一些 C++ 编码风格指南。数字 8 说“代表模板类型的名称应该是一个大写字母。”说明:“C++ 开发社区中的常见做法。这使得模板名称相对于所有其他使用的名称而言更加突出。”

真的那么普遍吗?我同意拥有template<class T> class vector {...} 很有意义。但是如果我有几个模板参数怎么办?我不认为<class A, class B><class AllocationPolicy, class ThreadingPolicy> 更容易理解。

您是否同意在某些情况下不应该应用给定的规则(根据 1... 是允许的)?

感谢您的想法!

【问题讨论】:

    标签: c++ templates coding-style


    【解决方案1】:

    我不太同意这种命名约定。对我来说,代表一个完全通用类型的模板参数作为一个简单的字母是有意义的——这是一个类型T,我真的不在乎哪个。但是如果对类型有任何要求,生成一个标识模板参数是什么的名称是有意义的:template <typename T, typename Allocator> struct container——第一个类型是通用的,任何T 都适合,但第二个是分配器.

    这与函数没有什么不同,你不希望你的参数被称为ab... 按顺序或外观,而是生成有意义的名称作为文档的一部分时间>。此外,如果开发样式指南,我会考虑在模板类的情况下要求模板参数的本地 typedef 以及对类型要求的静态断言(尽可能)。也就是说,至少在 概念 提供该功能之前。

    我认为 STL 是一个很好的库示例,您可以看到生成 typedef 有助于阅读代码(来自 g++ 4.2 stl):

    类:

    // from <vector> -> <bits/stl_vector.h>
    template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
    class vector : protected _Vector_base<_Tp, _Alloc>
    {
      // Concept requirements.
      typedef typename _Alloc::value_type _Alloc_value_type; // _Alloc contains value_type internal type
      __glibcxx_class_requires(_Tp, _SGIAssignableConcept)   // _Tp is assignable
    [...]
    public:
       typedef _Tp value_type;                 // from here on _Tp is not mentioned
       typedef typename _Tp_alloc_type::reference reference; // check + typedef
    [...]
       iterator begin() { 
       // without typedef:
       // __gnu_cxx::__normal_iterator<pointer, vector_type> begin() {
    [...]
       reference operator[](size_type __n)
       // _Tp& operator[](size_type __n)
    [...]
    
    // from <memory>
    template <typename _Tp>
    class auto_ptr 
    {
    [...]
        template <typename _Tp1>
        auto_ptr(auto_ptr<_Tp1>& __a) throw() 
    

    和功能:

    template <typename _InputIterator, typename _Tp>
    inline _InputIterator find( _InputIterator __first, _InputIterator __last, _Tp value ) {
      // concept requirements
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      [...]
    

    他们所有的名字都以_为前缀,或者是一个大写字母或第二个_,这是为实现保留的名字,他们更喜欢_Tp而不是_T,但最后你可以看到,当一个类型是generic时,它被称为_Tp_Tp1...,而当它附加一些特定要求时,选择一个更合理的名称。

    它们之间有一条细线,例如在std::vector 中,对泛型类型有实际要求:_Tp 必须是可赋值的,但归根结底,它是一个 主要是泛型类型。在一些有多个要求的容器中,将其称为 _Assignable 会很奇怪。

    【讨论】:

    • 正如您所写,_.__* 是为实现而保留的(在某些范围内),所以恕我直言,最好不要使用任何这样命名的标识符(即使它可能会赢)在实践中不会造成任何伤害)。
    • 你知道Tp中的p是从哪里来的吗?来自P 中的TyPe?
    【解决方案2】:

    我想这取决于你有多少参数。如果一个参数是一个类型并且它是唯一的参数为什么不能只是T?不过我同意你的观点,在多个参数的情况下,它们应该具有有意义的名称,原因与变量通常应该具有有意义的名称的原因相同。

    【讨论】:

    • 对我来说,这更多地取决于每个参数代表什么,而不是是否有多个参数:template &lt;typename T, typename U&gt; struct pair 是一种完全明智的方法,而template &lt;typename T, typename U&gt; class vector 缺少 U 必须是分配器,而不是任何泛型类型。
    【解决方案3】:

    模板类型的表达性名称当然是有序的。当某天在语言中引入概念时,它会更加有用(遗憾的是它们被 C++0x 删除了)。同时,模板参数类型的名称描述了对该给定类型的期望,至少是非正式的(概念会给它们一个形式,列出期望的类型和该类型必须具有的操作)。

    【讨论】:

      【解决方案4】:

      不同的编码标准会定义不同的命名。随便挑一个,坚持下去。

      我的偏好是具有描述性的名称,而不是一些通用类型名称 T(尽管在某些情况下还不错)。

      【讨论】:

        【解决方案5】:

        我认为单字母名称(在模板和其他方面)的主要问题是当您想要进行搜索和替换时。如果您的文本编辑器不包含 C++ 解析器(并且大多数不包含),那么单字母名称将导致大量您不希望的虚假匹配。使用更长/描述性的名称,OTOH,搜索和替换更有可能按预期工作。

        【讨论】:

          【解决方案6】:

          如果只是一个类型,我倾向于使用单字母标识符(T、U 等)。如果参数具有特殊的更有限的含义(谓词、分配器等),我会使用更具描述性的东西。

          但是,单字母标识符 (T) 可能会适得其反,因为它与宏名称冲突(请参阅 GCC 4.2 Template strange error),这对于较长的标识符(如果它们不使用与宏相同的 ALL_CAPS 约定)可能更不可能)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-01-12
            • 1970-01-01
            • 2019-04-22
            • 1970-01-01
            • 2012-08-03
            • 2021-12-18
            相关资源
            最近更新 更多