Coding conventions
  • Indent style is Allman (BSD) -like, ie. brace on the next line from a control statement, indented on the same level. In switch-case statements the cases are on the same indent level as the switch statement.
  • Indents use 4 spaces instead of tabs. Indents on empty lines should not be kept.
  • Class and struct names are in camelcase beginning with an uppercase letter. They should be nouns. For example DebugRenderer, FreeTypeLibrary, Graphics.
  • Functions are likewise in upper-camelcase. For example CreateComponent, SetLinearRestThreshold.
  • Variables are in lower-camelcase. Member variables have an underscore appended. For example numContacts, randomSeed_.
  • Constants and enumerations are in uppercase. For example Vector3::ZERO or PASS_SHADOW.
  • Pointers and references append the * or & symbol to the type without a space in between. For example Drawable* drawable, Serializer& dest.
  • The macro NULL and 0 should not be used for null pointers, nullptr is used instead.
  • override is used wherever possible.
  • using is used instead of typedef in type declarations.
  • enum class is not used because of legacy reasons.
  • Class definitions proceed in the following order:
    • public constructors and the destructor
    • public virtual functions
    • public non-virtual member functions
    • public static functions
    • public member variables
    • public static variables
    • repeat all of the above in order for protected definitions, and finally private
  • Header files are commented using one-line comments beginning with /// to mark them for Doxygen.
  • Inline functions are defined inside the class definitions where possible, without using the inline keyword.

It's recommended to follow C++ Core Guidelines (except items that contradict Urho legacy, e.g. ES.107, Enum.3, Enum.5)

Use this brief checklist to keep code style consistent among contributions and contributors:

  • Prefer inplace member initialization to initializer lists.
  • Prefer range-based for to old style for unless index or iterator is used by itself.
  • Avoid auto unless it increases code readability. More details here and here.
    • Use auto for verbose, unknown or redundant types. Example:
      auto iter = variables.Find(name); // verbose iterator type: HashMap<String, Variant>::Iterator
      for (auto& variable : variables) { } // verbose pair type: HashMap<String, Variant>::KeyValue
      auto model = MakeShared<Model>(context_); // type is already mentioned in the expression: SharedPtr<Model>
    • Use auto instead of manual type deduction via decltype and typename.