// III
template <
size_t N_CURRENT,
size_t N_END,
size_t N_BEGIN = N_CURRENT,
char ... Cr,
size_t SUBSTRING_LENGTH = N_END - N_BEGIN
>
constexpr static_string substr() const noexcept {
static_assert(N_END >= N_CURRENT, "static_string::substr(): N_END
must be more than or equal to N_CURRENT!");
return N_CURRENT == N_END
? static_string(SUBSTRING_LENGTH, Cr...)
: substr<N_CURRENT+1, N_END, N_BEGIN, Cr..., ' '>(); //causes a lot of recursion errors...
// note the ' ' in substr<N_CURRENT+1, B_END, B_BEGIN, Cr..., ' '> has been added for testing purposes.
}
对不起,标题有点含糊:我不知道到底是什么问题。 然而: 表达式N_CURRENT == N_END似乎被忽略,并且使用了后者的返回值。即使我将N_CURRENT == N_END更改为true,后者仍在使用。仅当我实际调用该函数时才会显示错误,例如
static_string str = str1.substr<4, 7>();
有人可以向我解释为什么会这样,并帮助我找到解决该问题的方法吗?非常感谢!
答案 0 :(得分:2)
问题的原因很简单,三元运算符的评估为时已晚:
N_CURRENT == N_END
? static_string(SUBSTRING_LENGTH, Cr...)
: substr<N_CURRENT+1, N_END, N_BEGIN, Cr..., ' '>()
这意味着仅在实例化以下条件之后才检查条件:
substr<N_CURRENT+1, N_END, N_BEGIN, Cr..., ' '>
三元运算符可以避免执行错误的路径,但不能避免编译。 为了使其正常工作,您应该使用以下C ++ 17功能:
if constexpr(N_CURRENT == N_END)
return static_string(SUBSTRING_LENGTH, Cr...);
else
return substr<N_CURRENT+1, N_END, N_BEGIN, Cr..., ' '>()
这样,else部分仅被部分解析,而没有实例化substr<>()
如果编译器不支持c ++ 17的if constexpr
,则必须针对不同的情况编写不同的功能,并使用std::enable_if
启用/禁用它们。 (由于我真的不知道其余代码的工作方式,所以我只是在猜测您的代码的外观。特别是,我不知道Cr ...是什么,所以很可能我做错了。我建议您接受这些想法并与他们合作。)
std::enable_if
应该在您的代码上起作用:
template <int N_CURRENT,
int N_END, int N_BEGIN,
int SUBSTRING_LENGTH,
class ...Params,
class = typename std::enable_if<N_CURRENT == N_END>::type >
constexpr auto do_substr(Params ...Cr)
{
return static_string(SUBSTRING_LENGTH, Cr...);
}
和 模板::类型> constexpr auto do_substr(参数... Cr) { 返回substr() }
并调用它而不是三元运算符:
return do_substr<N_CURRENT, N_END, N_BEGIN, Params...>(Cr...);
由于我不知道您的代码在做什么,因此我避免了参数包的完美转发,但是请随时使用
do_substr(Params && ...Cr)
和
std::forward<Params>(Cr)...