Skip to content

Instantly share code, notes, and snippets.

@Nekrolm
Last active July 24, 2024 23:49
Show Gist options
  • Save Nekrolm/31c8e811f96431c316e39d4096957f77 to your computer and use it in GitHub Desktop.
Save Nekrolm/31c8e811f96431c316e39d4096957f77 to your computer and use it in GitHub Desktop.
compile time boolean option list with C++23
#include <string>
#include <string_view>
#include <iostream>
#include <concepts>
void check_length(std::string_view sv)
{ std::cout << "check len\n"; }
void check_content(std::string_view sv)
{ std::cout << "check content\n"; }
// ... more other checks
// You had a function:
void my_great_function(const std::string& input) {
check_length(input);
check_content(input);
std::cout << "do great! " << input << "\n";
}
// then you'd decided you need an option to bypass checks:
// Option 1: BAD
void my_great_function_bad(const std::string& input, bool len_check = true, bool content_check = true) { };
// Option 2: Better
struct CheckOptions { bool len; bool content; };
void my_great_function_better(const std::string& input, CheckOptions opts = {.len = true, .content = true}) { }
// Option 3: Best
template <class T, auto... Vars>
concept OneOf = (std::same_as<T, decltype(Vars)> || ...);
constexpr struct {} SkipLengthCheck;
constexpr struct {} SkipContentCheck;
void my_great_function_best(const std::string& input,
OneOf<SkipLengthCheck, SkipContentCheck> auto... opts) {
struct: decltype(opts)... {} OptsSet;
if constexpr (not requires { auto(SkipLengthCheck) = OptsSet; }) {
check_length(input);
}
if constexpr (not requires { auto(SkipContentCheck) = OptsSet; }) {
check_content(input);
}
std::cout << "do great! " << input << "\n";
}
int main() {
std::cout << "-- call no parameters:\n";
my_great_function_best("hello");
std::cout << "-- call skip len:\n";
my_great_function_best("hello", SkipLengthCheck);
std::cout << "-- call skip content:\n";
my_great_function_best("hello", SkipContentCheck);
std::cout << "-- call skip both: \n";
my_great_function_best("hello", SkipContentCheck, SkipLengthCheck);
std::cout << "-- call skip both (different params order): \n";
my_great_function_best("hello", SkipLengthCheck, SkipContentCheck);
}
#include <string>
#include <string_view>
#include <iostream>
#include <concepts>
void check_length(std::string_view sv)
{ std::cout << "check len\n"; }
void check_content(std::string_view sv)
{ std::cout << "check content\n"; }
// ... more other checks
// You had a function:
void my_great_function(const std::string& input) {
check_length(input);
check_content(input);
std::cout << "do great! " << input << "\n";
}
// then you'd decided you need an option to add checks, disabled by default
// Option 1: BAD
void my_great_function_bad(const std::string& input, bool len_check = true, bool content_check = true) { };
// Option 2: Better
struct CheckOptions { bool len; bool content; };
void my_great_function_better(const std::string& input, CheckOptions opts = {.len = true, .content = true}) { }
// Option 3: Best
template <class T, auto... Vars>
concept OneOf = (std::same_as<T, decltype(Vars)> || ...);
constexpr auto CheckLength = [](const std::string& s) {
std::cout << "check len\n";
};
constexpr auto CheckContent = [](const std::string& s) {
std::cout << "check content\n";
};
constexpr auto AdditionalCheckLength = [](const std::string& s, int) {
std::cout << "add check len\n";
};
constexpr auto AdditionalCheckContent = [](const std::string& s, int) {
std::cout << "add check content\n";
};
void my_great_function_best(const std::string& input,
OneOf<CheckLength,
CheckContent,
AdditionalCheckLength,
AdditionalCheckContent> auto... checks) {
constexpr static struct: decltype(checks)... {} CheckList;
constexpr static auto for_checks_do = [](auto apply, auto... checks) {
([](auto check, auto apply) {
if constexpr (requires { check = CheckList; }) {
apply(check);
}
}(checks, apply), ...);
};
for_checks_do([&input](auto check) { check(input); },
CheckLength, CheckContent
);
for_checks_do([&input](auto check) { check(input, 42); },
AdditionalCheckLength, AdditionalCheckContent
);
std::cout << "do great! " << input << "\n";
}
int main() {
my_great_function_best("hello", CheckLength, AdditionalCheckContent);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment