C++ Core Guidelines 整理目录
模板规则
模板使用规则
T.1: Use templates to raise the level of abstraction of code
- 翻译: 使用模板提升代码的抽象层次.
- 原因: 模板允许编写更加通用和抽象的代码, 可以应用于各种不同的数据类型而无需重写代码.
T.2: Use templates to express algorithms that apply to many argument types
- 翻译: 使用模板表达适用于多种参数类型的算法.
- 原因: 这使得相同的算法逻辑可以在不同数据类型之间共享, 提高了代码复用性和灵活性.
T.3: Use templates to express containers and ranges
- 翻译: 使用模板表示容器和范围.
- 原因: 容器和范围是 C++中非常重要的概念, 通过模板实现可以支持多种数据类型的存储和操作.
T.4: Use templates to express syntax tree manipulation
- 翻译: 使用模板进行语法树的操作.
- 原因: 在编译器开发和其他需要处理语法结构的应用中, 模板能够提供强大的抽象能力, 简化复杂的结构化操作.
T.5: Combine generic and OO techniques to amplify their strengths, not their costs
- 翻译: 结合泛型和面向对象技术以放大它们的优势, 而不是增加成本.
- 原因: 合理结合这两种技术可以使程序设计既灵活又高效, 同时避免单一技术可能带来的局限性.
概念(Concept)使用规则
T.10: Specify concepts for all template arguments
- 翻译: 为所有模板参数指定概念.
- 原因: 使用概念可以帮助编译器在编译期进行类型检查, 确保传递给模板的参数符合预期的要求, 从而提高代码的安全性和可读性.
T.11: Whenever possible use standard concepts
- 翻译: 尽可能使用标准概念.
- 原因: 标准概念是广泛接受并经过充分测试的, 使用它们可以减少自定义概念的工作量, 并且有助于提升代码的一致性和互操作性.
T.12: Prefer concept names over auto
for local variables
- 翻译 : 在局部变量中优先选择概念名称而不是
auto
关键字. - 原因 : 虽然
auto
关键字可以简化代码, 但明确使用概念名称可以使代码意图更加清晰, 便于理解和维护.
T.13: Prefer the shorthand notation for simple, single-type argument concepts
- 翻译: 对于简单, 单一类型的参数概念, 优先使用简写符号.
- 原因: 简写符号不仅简洁, 而且易于阅读和理解, 尤其是在处理简单的模板参数时, 可以显著减少代码的复杂度.
概念(Concept)定义规则
T.20: Avoid "concepts" without meaningful semantics
- 翻译: 避免没有实际语义的概念.
- 原因: 没有明确语义的概念会导致代码难以理解和维护. 确保每个概念都有具体的含义和用途.
T.21: Require a complete set of operations for a concept
- 翻译: 要求概念具备完整的一组操作.
- 原因: 完整的操作集能够确保类型满足概念的所有要求, 从而避免在使用过程中出现意外错误.
T.22: Specify axioms for concepts
- 翻译: 为概念指定公理(axioms).
- 原因: 公理描述了概念的行为特性, 有助于编译器优化和用户理解概念的预期行为.
T.23: Differentiate a refined concept from its more general case by adding new use patterns
- 翻译: 通过添加新的使用模式来区分一个细化的概念与其更通用的情况.
- 原因: 这样可以明确不同概念之间的差异, 并使代码更具表达力和灵活性.
T.24: Use tag classes or traits to differentiate concepts that differ only in semantics
- 翻译: 使用标记类或特质(traits)来区分仅在语义上不同的概念.
- 原因: 标记类或特质可以帮助区分那些在实现上相同但在语义上有区别的概念, 从而提高代码的清晰度.
T.25: Avoid complementary constraints
- 翻译: 避免互补约束.
- 原因: 互补约束可能会导致不必要的复杂性和混淆, 应尽量简化约束条件以提高代码的可读性.
T.26: Prefer to define concepts in terms of use-patterns rather than simple syntax
- 翻译: 更倾向于根据使用模式而不是简单的语法来定义概念.
- 原因: 基于使用模式定义的概念更加直观和易于理解, 有助于编写出更自然, 更符合意图的代码.
T.30: Use concept negation (!C<T>
) sparingly to express a minor difference
- 翻译 : 尽量少用概念否定 (
!C<T>
) 来表示细微差异. - 原因: 概念否定会使代码逻辑变得复杂且难以理解, 尽量使用正向逻辑来表达需求.
T.31: Use concept disjunction (C1<T> || C2<T>
) sparingly to express alternatives
- 翻译 : 尽量少用概念析取 (
C1<T> || C2<T>
) 来表示备选方案. - 原因: 析取操作符会增加代码的复杂性, 尽量保持概念的简单性和明确性, 以提高代码的可读性和维护性.
模板接口规则
T.40: Use function objects to pass operations to algorithms
- 翻译: 使用函数对象将操作传递给算法.
- 原因: 函数对象可以包含状态, 并且通常比普通函数指针更高效. 它们允许算法接受不同的行为作为参数.
T.41: Require only essential properties in a template's concepts
- 翻译: 在模板的概念中仅要求必要的属性.
- 原因: 限制概念中的属性可以提高模板的灵活性和重用性, 避免不必要的约束.
T.42: Use template aliases to simplify notation and hide implementation details
- 翻译: 使用模板别名简化符号并隐藏实现细节.
- 原因: 模板别名可以使代码更加简洁易读, 并且有助于封装复杂类型定义.
T.43: Prefer using
over typedef
for defining aliases
- 翻译 : 定义别名时优先使用
using
而非typedef
. - 原因 :
using
语法更直观, 灵活, 尤其是在处理模板别名时更为方便.
T.44: Use function templates to deduce class template argument types (where feasible)
- 翻译: 使用函数模板推导类模板参数类型(在可行的情况下).
- 原因: 这样可以减少显式指定模板参数的需求, 使代码更加简洁.
T.46: Require template arguments to be at least semiregular
- 翻译 : 要求模板参数至少是半正规(
semiregular
)的. - 原因: 半正规类型具有默认构造函数和赋值操作符, 这使得它们更容易被模板使用.
T.47: Avoid highly visible unconstrained templates with common names
- 翻译: 避免使用常见的名称定义高度可见的无约束模板.
- 原因: 这可能会导致命名冲突和意外的行为, 应尽量确保模板名称具有唯一性和明确性.
T.48: If your compiler does not support concepts, fake them with enable_if
- 翻译 : 如果编译器不支持概念, 使用
enable_if
来模拟. - 原因 :
enable_if
可以帮助实现类似于概念的功能, 尽管不如原生概念那样直观和强大.
T.49: Where possible, avoid type-erasure
- 翻译: 尽量避免类型擦除.
- 原因: 类型擦除会增加运行时开销, 并可能导致性能下降和调试困难. 保持类型信息可以提高代码的效率和可维护性.
模板定义规则
T.60: Minimize a template's context dependencies
- 翻译: 尽量减少模板的上下文依赖.
- 原因: 减少依赖可以使模板更加独立和可重用, 降低维护成本并提高代码的灵活性.
T.61: Do not over-parameterize members (SCARY)
- 翻译: 不要过度参数化成员(SCARY).
- 原因: 过度参数化会导致不必要的复杂性和编译时间增加. SCARY 原则提倡通过限制模板参数来简化设计.
T.62: Place non-dependent class template members in a non-templated base class
- 翻译: 将非依赖类模板成员放在非模板基类中.
- 原因: 这样可以减少重复代码, 并使模板更易于管理和理解, 同时提高编译效率.
T.64: Use specialization to provide alternative implementations of class templates
- 翻译: 使用特化提供类模板的替代实现.
- 原因: 特化允许为特定类型提供优化或特定行为, 从而提高代码的性能和适用性.
T.65: Use tag dispatch to provide alternative implementations of functions
- 翻译: 使用标记调度(tag dispatch)为函数提供替代实现.
- 原因: 标记调度是一种技术, 可以根据传递给函数的不同标记选择不同的实现, 从而使代码更具灵活性和扩展性.
T.67: Use specialization to provide alternative implementations for irregular types
- 翻译: 使用特化为不规则类型提供替代实现.
- 原因: 对于某些特殊类型, 标准实现可能不适合, 特化可以帮助处理这些特殊情况.
T.68: Use {}
rather than ()
within templates to avoid ambiguities
- 翻译 : 在模板内部使用
{}
而不是()
以避免歧义. - 原因: 使用统一初始化语法(花括号)可以减少由于隐式类型转换引起的错误和歧义.
T.69: Inside a template, don't make an unqualified non-member function call unless you intend it to be a customization point
- 翻译: 在模板内部, 除非有意将其作为自定义点, 否则不要调用未限定的非成员函数.
- 原因: 未限定的调用可能会导致意外的行为, 特别是在模板被实例化时. 明确指定作用域可以避免此类问题.
模板与层次结构规则
T.80: Do not naively templatize a class hierarchy
- 翻译: 不要天真地将类层次结构模板化.
- 原因: 盲目模板化类层次结构可能导致复杂的依赖关系和编译时间增加. 应仔细考虑模板化的必要性和影响.
T.81: Do not mix hierarchies and arrays
- 翻译: 不要混合层次结构和数组.
- 原因: 层次结构和数组有不同的语义和用途, 混合使用可能导致代码难以理解和维护.
T.82: Linearize a hierarchy when virtual functions are undesirable
- 翻译: 当不希望使用虚函数时, 线性化层次结构.
- 原因: 线性化可以通过减少继承层次来简化设计, 适用于不需要多态行为的情况.
T.83: Do not declare a member function template virtual
- 翻译: 不要声明成员函数模板为虚函数.
- 原因: 虚函数模板在 C++中是无效的, 并且可能导致编译错误或未定义行为.
T.84: Use a non-template core implementation to provide an ABI-stable interface
- 翻译: 使用非模板核心实现提供 ABI 稳定的接口.
- 原因: 非模板实现可以确保二进制兼容性, 这对于库的发布和维护非常重要.
可变参数模板规则
T.100: Use variadic templates when you need a function that takes a variable number of arguments of a variety of types
- 翻译: 当你需要一个可以接受多种类型不定数量参数的函数时, 使用可变参数模板.
- 原因: 可变参数模板允许编写更加灵活和通用的函数, 适用于各种不同的参数组合.
T.101: How to pass arguments to a variadic template
- 翻译: 如何向可变参数模板传递参数.
- 原因: 理解如何正确传递参数是使用可变参数模板的基础, 确保调用时的行为符合预期.
T.102: How to process arguments to a variadic template
- 翻译: 如何处理可变参数模板中的参数.
- 原因: 处理参数的方式决定了模板的功能和效率, 理解这些方法有助于编写高效, 清晰的代码.
T.103: Don't use variadic templates for homogeneous argument lists
- 翻译: 不要对同质参数列表使用可变参数模板.
- 原因: 对于同质参数列表, 使用数组或标准容器通常更简单且高效.
元编程规则
T.120: Use template metaprogramming only when you really need to
- 翻译: 仅在确实需要时使用模板元编程.
- 原因: 模板元编程虽然强大, 但复杂度高且难以调试, 应谨慎使用.
T.121: Use template metaprogramming primarily to emulate concepts
- 翻译: 主要使用模板元编程来模拟概念.
- 原因: 在没有原生概念支持的情况下, 模板元编程可以帮助实现类似的概念功能.
T.122: Use templates (usually template aliases) to compute types at compile time
- 翻译: 使用模板(通常是模板别名)在编译时计算类型.
- 原因: 这种技术可以提高代码的灵活性, 并减少运行时开销.
T.123: Use constexpr
functions to compute values at compile time
- 翻译 : 使用
constexpr
函数在编译时计算值. - 原因 :
constexpr
函数可以在编译时进行计算, 从而提高性能并减少运行时开销.
T.124: Prefer to use standard-library TMP facilities
- 翻译: 尽量使用标准库 TMP(Template Metaprogramming)设施.
- 原因: 标准库提供了经过优化和测试的 TMP 工具, 使用它们可以减少错误并提高代码质量.
T.125: If you need to go beyond the standard-library TMP facilities, use an existing library
- 翻译: 如果需要超出标准库 TMP 设施的功能, 请使用现有的库.
- 原因: 现有的库通常已经解决了许多常见的 TMP 问题, 使用它们可以节省时间和精力.
其他模板规则
T.140: If an operation can be reused, give it a name
- 翻译: 如果一个操作可以被重用, 请为其命名.
- 原因: 命名重用的操作可以提高代码的可读性和可维护性, 避免重复代码.
T.141: Use an unnamed lambda if you need a simple function object in one place only
- 翻译: 如果只需要在一个地方使用简单的函数对象, 请使用匿名 lambda 表达式.
- 原因: 匿名 lambda 表达式可以使代码更加简洁, 避免不必要的命名和声明.
T.142: Use template variables to simplify notation
- 翻译: 使用模板变量简化符号.
- 原因: 模板变量可以减少冗余代码, 使代码更加简洁和易于理解.
T.143: Don't write unintentionally non-generic code
- 翻译: 不要无意中编写非泛型代码.
- 原因: 非泛型代码可能会限制代码的复用性和灵活性, 应尽量保持代码的泛型特性.
T.144: Don't specialize function templates
- 翻译: 不要特化函数模板.
- 原因: 函数模板的特化可能导致意外行为和复杂的依赖关系, 尽量避免使用.
T.150: Check that a class matches a concept using static_assert
- 翻译 : 使用
static_assert
检查类是否匹配某个概念. - 原因 :
static_assert
可以在编译时进行静态检查, 确保类满足概念的要求, 从而提高代码的安全性和可靠性.