This document describes the coding standards and style guidelines for Philote-Cpp.
Overview
Philote-Cpp follows the Google C++ Style Guide with one key exception:
Indentation: Use 4 spaces instead of 2 spaces
All other aspects of the Google C++ Style Guide apply unless explicitly stated otherwise in this document.
Indentation and Formatting
Indentation
Use 4 spaces for indentation (not tabs, not 2 spaces):
class MyClass {
public:
void MyMethod() {
if (condition) {
DoSomething();
}
}
};
class MyClass {
public:
void MyMethod() {
if (condition) {
DoSomething();
}
}
};
Line Length
Maximum line length is 80 characters (as per Google style).
void ShortFunction(int arg1, int arg2);
void LongFunctionName(int argument1, int argument2,
int argument3, int argument4);
void LongFunctionName(int argument1, int argument2, int argument3, int argument4, int argument5);
Braces
Use K&R style bracing (opening brace on same line):
if (condition) {
DoSomething();
}
class MyClass {
};
void Function() {
}
if (condition)
{
DoSomething();
}
Naming Conventions
Class Names
Use PascalCase for class names:
class ExplicitDiscipline { };
class DisciplineServer { };
class MyCustomDiscipline { };
Function Names
Use PascalCase for function names:
void ComputeFunction();
void GetInfo();
void SetVariableMeta();
Variable Names
Use snake_case for local variables and function parameters:
int variable_count = 0;
std::string discipline_name;
double computation_result;
void ProcessData(const Variables& input_variables,
Variables& output_variables) {
}
Member Variables
Use snake_case with a trailing underscore for private member variables:
class MyClass {
public:
void SetName(const std::string& name) { name_ = name; }
private:
std::string name_;
int counter_;
std::vector<double> data_;
};
Constants
Use kConstantName (k prefix with PascalCase):
const int kMaxIterations = 1000;
const double kTolerance = 1e-6;
const char* kDefaultServerAddress = "localhost:50051";
Enumerations
Use PascalCase for enum names and kEnumValue for enum values:
enum VariableType {
kInput,
kOutput,
kResidual
};
Namespace
Use lowercase for namespace names:
}
namespace philote::internal {
}
Definition discipline.h:43
File Organization
Header Files
Header files should use .h extension:
discipline.h
explicit.h
variable.h
Implementation Files
Implementation files should use .cpp extension:
discipline.cpp
explicit.cpp
variable.cpp
File Structure
Every file should start with a copyright header:
Header Guards
Use #pragma once for header guards (preferred) or traditional include guards:
Or:
#ifndef PHILOTE_DISCIPLINE_H
#define PHILOTE_DISCIPLINE_H
#endif
Include Order
Order includes as follows:
- Related header (for .cpp files)
- C system headers
- C++ standard library headers
- Other libraries' headers
- Project headers
Separate each group with a blank line:
#include <string.h>
#include <memory>
#include <string>
#include <vector>
#include <grpcpp/grpcpp.h>
Comments and Documentation
Class Documentation
Use Doxygen-style comments for classes:
class ExplicitDiscipline : public Discipline {
};
Function Documentation
Document public functions with Doxygen comments:
void Compute(const Variables& inputs, Variables& outputs);
Inline Comments
Use // for single-line comments:
double gradient = (f1 - f0) / epsilon;
SomeComplexWorkaround();
Use /* */ for multi-line explanatory comments:
TODO Comments
Use TODO comments with your name or GitHub issue:
Language Features
C++ Version
Philote-Cpp uses C++20. Modern C++ features are encouraged:
auto it = variables.find("x");
for (const auto& [name, variable] : variables) {
ProcessVariable(name, variable);
}
auto [value, success] = TryGetValue();
Smart Pointers
Use smart pointers instead of raw pointers:
std::unique_ptr<Server> server = builder.BuildAndStart();
std::shared_ptr<Channel> channel = CreateChannel(address);
Server* server = builder.BuildAndStart();
Const Correctness
Use const wherever possible:
void ProcessData(const Variables& inputs) {
const double value = inputs.at("x")(0);
}
void ProcessData(Variables& inputs) {
double value = inputs.at("x")(0);
}
References vs Pointers
Prefer references over pointers when possible:
void Process(const Variable& input);
void Process(const Variable* optional_param = nullptr);
void Process(const Variable* input);
Class Design
Inheritance
Use override keyword for virtual function overrides:
class MyDiscipline : public ExplicitDiscipline {
public:
void Setup() override;
void Compute(const Variables& inputs,
Variables& outputs) override;
};
Access Specifiers
Order class members as: public, protected, private:
class MyClass {
public:
MyClass();
void PublicMethod();
protected:
void ProtectedMethod();
private:
void PrivateMethod();
int private_member_;
};
Constructor Initialization
Use member initialization lists:
MyClass::MyClass(int value, const std::string& name)
: value_(value),
name_(name),
counter_(0) {
}
MyClass::MyClass(int value, const std::string& name) {
value_ = value;
name_ = name;
counter_ = 0;
}
Error Handling
Exceptions
Use exceptions for error handling:
if (!IsValid(input)) {
throw std::invalid_argument("Input must be positive");
}
Assertions
Use assertions for internal consistency checks:
#include <cassert>
void Process(const Variable& var) {
assert(var.Size() > 0);
}
Error Messages
Provide clear, actionable error messages:
throw std::runtime_error(
"Failed to connect to server at " + address +
": connection refused. Check that the server is running.");
throw std::runtime_error("Error");
Best Practices
RAII
Follow RAII (Resource Acquisition Is Initialization) principle:
{
std::unique_ptr<Resource> resource = AcquireResource();
UseResource(resource.get());
}
Resource* resource = AcquireResource();
UseResource(resource);
delete resource;
Avoid Global Variables
Minimize use of global variables:
int global_counter = 0;
class Counter {
public:
void Increment() { count_++; }
private:
int count_ = 0;
};
Use Standard Library
Prefer standard library over custom implementations:
std::vector<double> data;
std::map<std::string, Variable> variables;
MyCustomVector<double> data;
MyCustomMap<std::string, Variable> variables;
Minimize Header Dependencies
Use forward declarations where possible:
class Variable;
class MyClass {
void Process(const Variable& var);
};
Code Examples
Good Example - Explicit Discipline
public:
void Setup() override {
}
const double x = inputs.at("x")(0);
const double y = inputs.at("y")(0);
outputs.at("f_xy")(0) = (x - 3.0) * (x - 3.0) +
x * y +
(y + 4.0) * (y + 4.0) - 3.0;
}
};
Definition paraboloid_server.cpp:48
void AddInput(const std::string &name, const std::vector< int64_t > &shape, const std::string &units)
Declares an input.
void AddOutput(const std::string &name, const std::vector< int64_t > &shape, const std::string &units)
Declares an output.
Explicit discipline class.
Definition explicit.h:263
std::map< std::string, philote::Variable > Variables
Definition variable.h:404
Tools
ClangFormat (Optional)
A .clang-format configuration file is provided to automatically format code:
# Format a single file
clang-format -i src/discipline.cpp
# Format all source files
find src include -name '*.cpp' -o -name '*.h' | xargs clang-format -i
Note: The .clang-format file is configured for 4-space indentation.
Editor Configuration
Configure your editor to use 4 spaces for indentation:
VS Code (.vscode/settings.json):
{
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.detectIndentation": false
}
Vim (.vimrc):
set tabstop=4
set shiftwidth=4
set expandtab
CLion/IntelliJ: Go to Settings → Editor → Code Style → C/C++ → Tabs and Indents
- Tab size: 4
- Indent: 4
- Use spaces: ✓
Code Review Checklist
When reviewing code, check for:
- [ ] 4-space indentation used consistently
- [ ] Line length does not exceed 80 characters
- [ ] Naming conventions followed (PascalCase, snake_case, etc.)
- [ ] Copyright header present in new files
- [ ] Public functions documented with Doxygen comments
- [ ]
const used where appropriate
- [ ]
override keyword used for virtual functions
- [ ] Smart pointers used instead of raw pointers
- [ ] Exceptions used for error handling with clear messages
- [ ] No global variables introduced
- [ ] RAII principles followed
- [ ] Standard library used where appropriate
References
Questions
If you have questions about coding style or encounter situations not covered in this guide:
- Check the Google C++ Style Guide
- Look at existing code in the project for examples
- When in doubt, prioritize clarity and consistency with existing code
- Open an issue or discussion on GitHub for guidance