我们如何处理用户定义文字输入中的错误



假设我想定义一个积分百分比,如下所示:

constexpr int operator""_percent (char const * literal)
{
int percent(0);
for(; *literal != ''; ++literal)
{
if(*literal >= '0' && *literal <= '9')
{
percent *= 10;
percent += *literal - '0';
if(percent > 100)
{
...what do we do here?...
}
}
else
{
...what do we do here?...
}
}
return percent;
}

我曾想过投掷,但我记得constexprthrow不太匹配(或者这只适用于C++14及更高版本?(。在这种情况下,惯例是什么?在用户定义的文字运算符中报告错误的正确方法是什么?

注意:我目前正在使用C++17,但计划很快切换到C++20。

我真的不知道这种情况的常见做法是什么,但我会在下面给出一些想法。


使用C++20,可以使文字运算符consteval而不是constexpr

一旦出现错误,您就可以抛出异常。constexpr/consteval函数中允许throw表达式本身,但实际上抛出使其不是一个常量子表达式。由于consteval函数调用必须是常量表达式,因此程序在出现错误时会出现格式错误,编译器必须对其进行诊断


对于C++17,您仍然可以抛出异常,但consteval不可用。

对于有效的文字来说,这不是问题。只要不计算throw表达式,对文字运算符的调用仍然可以是常量子表达式。

但是,如果文本无效,如果它没有在需要常量表达式的上下文中使用,则通常不会得到编译时诊断。

相反,当计算文字时,您将在程序执行期间引发异常。这可能是不可取的,例如,如果文字应该在noexcept函数中使用。

或者,您也可以使用assert而不是抛出异常。由于C++17,如果参数的计算结果为true,则保证它是一个常量子表达式。

如果断言失败,您也不会得到编译时错误,相反,当计算文字时,程序将中止。

使用NDEBUG宏,断言可以在发布版本中删除。这不会影响异常规范,但您仍然需要决定如何处理发布版本中未在调试版本测试中发现的错误。这可能不够安全,不适合您使用。

我不认为有任何C++17方法可以强制编译时出错。


正如我在对这个问题的评论中提到的,我对我的建议是否正确/好有一些怀疑。所以请也读一遍。

最新更新