static_assert
/ 3 min read
Table of Contents
static_assert is one of those C++11 features that makes debugging so much easier. It lets you check conditions at compile time instead of discovering problems at runtime.
What static_assert Actually Does
It evaluates a condition at compile time. If the condition is false, compilation fails with your custom error message:
static_assert(sizeof(int) == 4, "This code assumes 32-bit integers");// Compilation fails if int is not 4 bytesThe condition must be something the compiler can evaluate at compile time - no runtime values allowed.
Why This Is Useful
Before static_assert, wrong assumptions would lead to runtime bugs or undefined behavior. Now you catch them immediately:
template<typename T>class MyVector { static_assert(std::is_arithmetic_v<T>, "T must be a numeric type"); // Fails compilation if someone tries MyVector<std::string>};When I Actually Use static_assert
Most of the time, I use static_assert in these situations:
- Template constraints: Making sure template parameters are what I expect:
template<typename T>void serialize(const T& obj) { static_assert(std::is_trivially_copyable_v<T>, "Type must be trivially copyable for serialization"); // Now I know memcpy is safe}- Platform assumptions: Ensuring the code works on the target platform:
static_assert(sizeof(void*) == 8, "This code requires 64-bit pointers");static_assert(std::numeric_limits<double>::is_iec559, "IEEE 754 floating point required");- Array size validation: Making sure arrays have the expected size:
constexpr size_t BUFFER_SIZE = 1024;static_assert(BUFFER_SIZE >= 512, "Buffer too small for protocol");static_assert(BUFFER_SIZE % 64 == 0, "Buffer size must be multiple of 64");- Enum validation: Ensuring enum values are in expected ranges:
enum class Priority { Low = 1, Medium = 5, High = 10 };static_assert(static_cast<int>(Priority::High) <= 10, "Priority values must be <= 10");C++17 Improvement
C++17 made the error message optional:
// C++11 stylestatic_assert(condition, "Error message required");
// C++17 stylestatic_assert(condition); // Uses default error messageI still prefer providing custom messages - they make debugging much faster.
The Pattern I Use
I put static_assert checks right where assumptions matter:
template<typename T, size_t N>class FixedArray { static_assert(N > 0, "Array size must be positive"); static_assert(N < 10000, "Array size seems unreasonably large");
T data_[N];public: void unsafe_access(size_t index) { static_assert(std::is_trivial_v<T>, "unsafe_access only for trivial types"); // Direct memory access without bounds checking }};Real World Example
Here’s how I use it in practice for a memory pool:
template<typename T, size_t Count>class ObjectPool { static_assert(Count > 0, "Pool must have at least one object"); static_assert(sizeof(T) >= sizeof(void*), "Objects too small for free list"); static_assert(alignof(T) >= alignof(void*), "Alignment requirements not met");
// Implementation...};The best part? All these checks happen at compile time, so there’s zero runtime cost. Your program either compiles correctly or fails fast with a clear error message.