int run(std::string type, std::string interval)
{
if(type == "ST"){
if(interval == "SEC"){
constexpr unsigned int N = 10;
Runner<N> data();
data.parse();
} else{
constexpr unsigned int N = 20;
Runner<N> data();
data.parse();
}
}
else if(type == "JST"){
constexpr unsigned int N = 23;
Runner<N> data();
data.parse();
}
else{
constexpr unsigned int N = 5;
Runner<N> data();
data.parse();
}
}
I want to reduce the if statements and do the conditional checks on a separate function:
constexpr unsigned int arraysize(std::string type, std::string interval){
if(type == "ST"){
if(interval == "SEC"){
return 10;
} else{
return 20;
}
}
else if(type == "JST"){
return 23;
}
else{
return 5;
}
}
However this doesn't work because a constexpr function cannot have a parameter of nonliteral type std::string.
Is there a better way to take out conditional checks so that I end up with something like this:
int run(std::string type, std::string interval)
{
constexpr unsigned int N = arraysize(type, interval);
Runner<N> data();
data.parse();
}
CodePudding user response:
run
as you are showing can't work, even in principle, because you want N
to be runtime-dependent. N
can't be constexpr
.
Alternative approach:
template<auto V>
inline constexpr auto constant = std::integral_constant<decltype(V), V>{};
template<typename F>
void apply_with_arraysize(F&& f, std::string type, std::string interval){
if(type == "ST"){
if(interval == "SEC"){
f(constant<10>);
} else{
f(constant<20>);
}
}
else if(type == "JST"){
f(constant<23>);
}
else{
f(constant<5>);
}
}
int run(std::string type, std::string interval)
{
apply_with_arraysize([](auto N){
Runner<N()> data; // N instead of N() also ok, if `Runner` doesn't use `auto` non-type template argument
data.parse();
}, type, interval);
}
CodePudding user response:
Another alternative, with more overhead, is the std::variant
approach:
std::variant<
std::integral_constant<unsigned, 10>,
std::integral_constant<unsigned, 20>,
std::integral_constant<unsigned, 23>,
std::integral_constant<unsigned, 5>,
>
arraysize(std::string type, std::string interval){
if (type == "ST") {
if (interval == "SEC") {
return std::integral_constant<unsigned, 10>();
} else {
return std::integral_constant<unsigned, 20>();
}
} else if (type == "JST") {
return std::integral_constant<unsigned, 23>();
} else {
return std::integral_constant<unsigned, 5>();
}
}
int run(std::string type, std::string interval)
{
std::visit(
[](auto N){
Runner<N> data{};
data.parse();
},
arraysize(type, interval));
}