模板类型的命名约定是什么?

37

传统上,模板类型的名称仅为单个大写字母:

template<class A, class B, class C>
class Foo {}; 

但是我犹豫不决,因为这样做不具描述性且难以阅读。因此,这样做会更好:

template<class AtomT, class BioT, class ChemT>
class Foo {}; 

我也倾向于认为以下做法不错:

template<class ATOM, class BIO, class CHEM>
class Foo {}; 

这会使它们突出显示(而且,这又是大写字母)。你有什么意见?

8个回答

48
对于C++模板,我有几种模式:
如果只有一个模板参数,我会将其命名为T(或嵌套模板的U、V)。
当有多个参数且使用不是立即明显的时候,我会使用带有T前缀的描述性名称。例如,TKey、TValue、TIdentifiier等...这使得参数在整个模板使用中相当容易被发现。
但我会避免使用全大写版本。大多数人在C/C++中使用全大写标识符来表示宏定义。重复这种模式作为模板参数可能会在未来让人感到困惑。

2
...并且也可能会混淆编译器。尝试使用#include <windows.h>模板<class ATOM> class Foo {}; - Andreas Magnusson
我不使用T作为前缀,因为它是“Borland”某些产品使用的相同前缀,对我来说有点混淆。 - Ismael
T前缀还允许您将无前缀名称用作通用方法名称(或命名空间中的任何其他符号)。例如,访问器const TValue&Value() const {return value_;} - Mark Lakata

8

我使用约定的TName作为模板参数,使用NameT作为存储的模板参数。

template <typename TFirst, typename TSecond>
class Templated
{
    typedef TFirst FirstT;
    typedef TSecond SecondT;
}

typedef Templated<int, std::string> MyTemplated;
...
const MyTemplated::FirstT size;

存储模板类型有什么意义呢?它们是不同的。我只是展示了如何命名这些存储的类型。这是我的个人约定。 - Mykola Golubyev

4

通常,如果只有一个类型参数,则传统的方法是使用T。 如果有多个,则使用T作为前缀,例如TAtom。 “T”前缀有助于立即看到它是类型参数。 对于单个类型参数,使用TAtom也是有效的。


2

在模板中,不应使用特殊的命名约定,只需使用与其他类型(例如类或变量)相同的约定即可。在代码中,您处理模板类型/值或普通类型/值时不应有任何区别。


对于参数化类型的名称,如Foo<int>,True。但问题是关于类型参数名称,即模板Foo<T>中的T。因此它不是一种类型,而是一个参数名称。 - Pete Kirkham
请注意,类型参数仅由模板本身访问,为了使它们可用于您的模板用户,您必须对它们进行typedef(例如, template <typename FooT> ... { typedef FooT Foo; };),因此,如果您仅使用标准约定,可能会出现名称冲突。 - Sebastian Mach
自 2009 年以来,你的观点是否有所改变?人们使用 mNamem_name 来表示成员变量,使用匈牙利命名法来表示 szName 等 - 如果有约定来支持实例和参数,我不明白为什么这些约定不能扩展到模板。如果类型或实例类型根本不同,我认为你应该同时使用或不使用约定。(元规则用于元编程!) - John P
我对于 Foo_t<T> 的主要论点是提供 Foo(T) -> Foo_t<T>(当类型不需要显式指定而是通过 ADL/SFINAE 推断时,前缀或后缀被省略;因此通过输入 Foo_t,你就知道需要模板参数而不是等到编译器报错)-- 看看有多少 SO 问题询问为什么我们需要 make_tuple/make_pair - John P

1

如果我有一个带有一个类型参数的类,我会使用名称T。这也意味着该类中的所有操作都与T一起工作。

如果我有几个参数,我会像您的示例AtomT、BioT一样命名。
如果模板参数不是我们在类中使用的对象类型,例如策略、比较器或函数对象,则我会使用没有T的名称,例如ThreadStrategy、Compare。

有时为了避免混合风格,我会在类中进行typedefs:
typedef T value_type;

--
Boost命名约定(http://www.boost.org/development/requirements.html#Naming_consistency)关于模板参数如下:
模板参数名称以大写字母开头。


1

我尝试遵循我的编译器供应商使用的概念:既不太短,也不太冗长。并且帮助我阅读使用标准模板时收到的错误消息。(这也是我从const T&切换到T const&的另一个原因)。类似于:

template <class Ty, class Container>
class my_algo { ...

我的编译器通常会使用:

template <class _Ty, class _Container>
class std_algo { ...

5
我认为你已经知道这一点了,但是对于其他人来说,请注意他没有使用前导下划线。 这些下划线是保留给编译器的。也就是说,标准库模板可以使用_Ty,但用户不行。Ty是合法的,因为它不以下划线开头。 - jalf
@jalf:+1。非常好的发现 :) 我太懒了,没有触及这个鲜为人知但“以后可能会反咬你一口”的要点。 - dirkgently
1
凡是神仙可以做的事,凡人不可越雷池一步。 - Frank
长期的遵从规则是一种漫长而费力的过程,而通过示例则可以快速、高效地实现。 - dirkgently
2
有趣的是,Dinkumware(您的标准库供应商)使用“_Ty”而不是“T”,以避免干扰使用“T”的用户。我完全不会批评您的理由,但有点有趣的是,他们产生了他们试图避免的东西。 :) - Patrick Niedzielski

1
在我们的店铺中,我们使用匈牙利命名法。模板参数只是像其他参数一样的参数,除了它们不是常量,也不是变量,而是类型。
template< typename at_Container, typename at_Functor > 
at_Functor& foreach( const at_Container& ac_Cont, at_Functor& av_Func ) {
    return std::foreach( ac_Cont.begin(), ac_Cont.end(), av_Func );
}

前缀描述类型,而名称则旨在说明参数在定义函数的上下文中所扮演的角色。


0

在命名模板参数类型名称时,我遵循命名类和结构体的相同一般约定,即将每个单词的第一个字母大写,例如:

class MyGizmo
{
};

struct Thingy
{
};

class TPSReport 
{
};


template<class ValType> ...

template<typename Number> ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接