通过检查字符串条件定义constexpr变量


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();
}
}

我想减少if语句,并对一个单独的函数进行条件检查:

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;
}
}

然而,这并不起作用,因为constexpr函数不能具有非迭代类型std::string的参数。

有没有更好的方法来进行条件检查,这样我就可以得到这样的结果:

int run(std::string type, std::string interval)
{
constexpr unsigned int N = arraysize(type, interval);
Runner<N> data();
data.parse();
}

run无法工作,即使在原则上也是如此,因为您希望N依赖于运行时。N不能是constexpr

替代方法:

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);
}

另一种开销更大的替代方案是std::variant方法:

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));
}

最新更新