Add compile-time-settings-check.md
This commit is contained in:
parent
7f1167e1be
commit
b21d15b981
106
cpp/compile-time-settings-check.md
Normal file
106
cpp/compile-time-settings-check.md
Normal 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");
|
||||
|
|
||||
```
|
||||
Loading…
Reference in New Issue
Block a user