Header Organization¶
Goal: Fast compilation, minimal coupling, clear dependencies
Include Order (MANDATORY)¶
// 1. Corresponding header (if .cpp file)
#include "audio_processor.hpp"
// 2. C standard library
#include <cmath>
#include <cstdint>
// 3. C++ standard library
#include <algorithm>
#include <memory>
#include <vector>
// 4. Third-party libraries
#include <juce_audio_basics/juce_audio_basics.h>
// 5. AudioLab foundation
#include <audiolab/types.hpp>
// 6. AudioLab core
#include <audiolab/core/buffer.hpp>
// 7. Local headers (same module)
#include "internal_helper.hpp"
Rationale: Detects missing includes in own header early
Header Guards¶
Use #pragma once:
Why: Simpler than include guards, supported by all modern compilers
Header Content Structure¶
#pragma once
/**
* @file filename.hpp
* @brief Brief description
*
* Detailed description if needed.
*/
// Includes (ordered as above)
#include <...>
// Namespace
namespace audiolab {
// Forward declarations (if needed)
class SomeClass;
// Type aliases
using SomeAlias = int;
// Constants
constexpr int SOME_CONSTANT = 42;
// Class/struct declarations
class MyClass {
// ...
};
// Inline function definitions (if small)
inline int small_function(int x) {
return x * 2;
}
} // namespace audiolab
What Goes in Headers¶
✅ Always in Headers¶
- Class declarations
- Inline functions (small, hot path)
- Template definitions
- Constants (
constexpr) - Type aliases
- Enums
❌ Never in Headers¶
using namespace(pollutes namespace)- Large function definitions (unless template/inline)
- Static variables with external linkage
- Implementation details
Header vs Implementation (.cpp)¶
Header (.hpp)¶
#pragma once
class AudioProcessor {
public:
void process(Sample* buffer, BlockSize size);
private:
float calculate_gain(); // Declaration only
float gain_;
};
Implementation (.cpp)¶
#include "audio_processor.hpp"
void AudioProcessor::process(Sample* buffer, BlockSize size) {
// Implementation
}
float AudioProcessor::calculate_gain() {
// Implementation
}
Inline Functions¶
When to inline: - Small (1-3 lines) - Hot path (called frequently) - Header-only libraries
Template Headers¶
Templates MUST be in headers:
template<typename T>
class RingBuffer {
void push(const T& value) {
// Implementation in header
}
};
Include What You Use (IWYU)¶
Only include what you actually use:
// ❌ Bad
#include <audiolab/audiolab.hpp> // Includes everything
// ✅ Good
#include <audiolab/types.hpp> // Only what's needed
Compilation Firewall (PIMPL)¶
For stable ABI, use PIMPL pattern:
// public_class.hpp
class PublicClass {
public:
PublicClass();
~PublicClass();
void do_something();
private:
struct Impl; // Forward declaration
std::unique_ptr<Impl> impl_; // Pointer to implementation
};
// public_class.cpp
struct PublicClass::Impl {
// Private implementation details
int some_data;
};
PublicClass::PublicClass() : impl_(std::make_unique<Impl>()) {}
PublicClass::~PublicClass() = default;
Remember: Headers are compiled many times. Keep them minimal.