Add compile-time-settings-check.md

This commit is contained in:
Andreas Tsouchlos 2025-04-14 15:34:24 +02:00
parent 7f1167e1be
commit b21d15b981

View File

@ -0,0 +1,106 @@
It is sometimes useful to be able to verify that certain settings are valid, at
compile time. An easy approach to do this is to pass the settings as non-type
template parameters and use `static_assert()`.
The code snippet below demonstrates an approach which doesn't require templates
and cleanly separates the verification logic from the rest of the code.
```cpp
namespace i2c {
//
//
// Driver Settings
//
//
struct Settings {
int sclPin = 0;
int sdaPin = 0;
std::size_t freqHz = 1'000'000;
};
namespace detail {
struct SettingsChecker {
public:
consteval SettingsChecker(Settings settings) : mSettings{settings} {
bool validPinSettings =
(settings.sclPin == 1 && settings.sdaPin == 2) ||
(settings.sclPin == 3 && settings.sdaPin == 4);
bool validFreqSettings =
(settings.freqHz < 10'000'000) && (settings.freqHz > 100);
// Exceptions thrown in consteval functions lead to compile time errors
if (!validPinSettings) throw std::logic_error("Wrong I2C pin settings");
if (!validFreqSettings)
throw std::logic_error("Wrong I2C frequency settings");
}
constexpr operator Settings() const {
return mSettings;
}
private:
Settings mSettings;
};
} // namespace detail
//
//
// Driver class
//
//
class Driver {
public:
Driver(detail::SettingsChecker settings) : mSettings(settings) {
}
private:
Settings mSettings;
};
} // namespace i2c
//
//
// Usage
//
//
int main() {
constexpr i2c::Settings settings1 = {
.sclPin = 1, .sdaPin = 2, .freqHz = 1'000'000};
i2c::Driver driver1{settings1}; // Compiles
constexpr i2c::Settings settings2 = {
.sclPin = 1, .sdaPin = 4, .freqHz = 1'000'000};
i2c::Driver driver2{settings2}; // Compile time error
}
```
Compiling the above code leads to the following error:
```bash
compile-time-settings-check.cpp: In function int main():
compile-time-settings-check.cpp:88:34: error: call to consteval function i2c::detail::SettingsChecker(settings2) is not a constant expression
88 | i2c::Driver driver2{settings2}; // Compile-time error
| ^
compile-time-settings-check.cpp:88:34: in constexpr expansion of i2c::detail::SettingsChecker(settings2)
compile-time-settings-check.cpp:36:32: error: expression <throw-expression> is not a constant expression
36 | if (!validPinSettings) throw std::logic_error("Wrong I2C pin settings");
|
```