From b21d15b981ac6e7a9b8e99e3f41da239332d2fb0 Mon Sep 17 00:00:00 2001 From: Andreas Tsouchlos Date: Mon, 14 Apr 2025 15:34:24 +0200 Subject: [PATCH] Add compile-time-settings-check.md --- cpp/compile-time-settings-check.md | 106 +++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 cpp/compile-time-settings-check.md diff --git a/cpp/compile-time-settings-check.md b/cpp/compile-time-settings-check.md new file mode 100644 index 0000000..7f5742d --- /dev/null +++ b/cpp/compile-time-settings-check.md @@ -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 ‘’ is not a constant expression + 36 | if (!validPinSettings) throw std::logic_error("Wrong I2C pin settings"); + | +```