在Consteval d时提供ConstexPr-Saf的简化异常消息
想象一下这个简单的constexpr
函数:
// Whatever, the exact values don't matter for this example
constexpr float items[100] = { 1.23f, 4.56f };
constexpr int length = 12;
constexpr float getItem(int index)
{
if (index < 0 || index >= length)
{
// ArrayIndexOutOfRangeException has a constructor that takes a const char* and one that takes a std::string.
throw ArrayIndexOutOfRangeException("You did a bad.");
}
return items[index];
}
您可以这样使用它:
int main()
{
constexpr float f1 = getItem( 0); std::cout << f1 << std::endl; // Works fine
constexpr float f2 = getItem( 1); std::cout << f2 << std::endl; // Works fine
constexpr float f3 = getItem(-1); std::cout << f3 << std::endl; // Does not compile: "constexpr variable 'f3' must be initialized by a constant expression", "subexpression not valid in a constant expression"
constexpr float f4 = getItem(20); std::cout << f4 << std::endl; // Does not compile: "constexpr variable 'f4' must be initialized by a constant expression", "subexpression not valid in a constant expression"
return 0;
}
太好了!屁股的重量!
volatile int i;
i = 123; // As a placeholder for something like this: std::cin >> i;
float f5 = getItem(i);
std::cout << f5 << std::endl;
在投掷'arrayindexoutofrangeException'的实例'和“ what what():您做了不好的实例之后,这将在运行时投入运行时。
好的,这不是很有帮助,我想创建一个更好的错误消息:
constexpr float getItem(int index)
{
if (index < 0 || index >= length)
{
std::stringstream stream;
stream << "You did a bad. getItem was called with an invalid index (" << index << "), but it should have been non-negative and less than the total number of items (" << length << ").";
throw ArrayIndexOutOfRangeException(stream.str());
}
return items[index];
}
但是不允许这样做:“非文字类型'std :: stringstream'(aka'basic_stringstream'的变量)无法在constexpr函数中定义。<<<<<<<<<<<<<<<<<<<<<<<< br> 我可以为编译时版提供更简单的错误消息,并且只有在运行时版本中进行复杂的字符串操作。
那...怎么样?
请注意,这是C ++ 17(一些GCC风味),可能没有C ++ 20具有的某些与ConstexPR相关的功能。
其他代码要求该函数保持constexpr
。
如果可能的话,我想避免重复该功能。
Imagine this simple constexpr
function:
// Whatever, the exact values don't matter for this example
constexpr float items[100] = { 1.23f, 4.56f };
constexpr int length = 12;
constexpr float getItem(int index)
{
if (index < 0 || index >= length)
{
// ArrayIndexOutOfRangeException has a constructor that takes a const char* and one that takes a std::string.
throw ArrayIndexOutOfRangeException("You did a bad.");
}
return items[index];
}
You can use it like this:
int main()
{
constexpr float f1 = getItem( 0); std::cout << f1 << std::endl; // Works fine
constexpr float f2 = getItem( 1); std::cout << f2 << std::endl; // Works fine
constexpr float f3 = getItem(-1); std::cout << f3 << std::endl; // Does not compile: "constexpr variable 'f3' must be initialized by a constant expression", "subexpression not valid in a constant expression"
constexpr float f4 = getItem(20); std::cout << f4 << std::endl; // Does not compile: "constexpr variable 'f4' must be initialized by a constant expression", "subexpression not valid in a constant expression"
return 0;
}
Great! BUTT WEIGHT!
volatile int i;
i = 123; // As a placeholder for something like this: std::cin >> i;
float f5 = getItem(i);
std::cout << f5 << std::endl;
This throws at runtime with "terminate called after throwing an instance of 'ArrayIndexOutOfRangeException'" and "what(): You did a bad."
Ok, that's not very helpful and I want to create a better error message:
constexpr float getItem(int index)
{
if (index < 0 || index >= length)
{
std::stringstream stream;
stream << "You did a bad. getItem was called with an invalid index (" << index << "), but it should have been non-negative and less than the total number of items (" << length << ").";
throw ArrayIndexOutOfRangeException(stream.str());
}
return items[index];
}
But that's not allowed: "variable of non-literal type 'std::stringstream' (aka 'basic_stringstream') cannot be defined in a constexpr function".
I'd be OK with having a simpler error message for the compile-time version and only do the complicated string manipulation in the run-time version.
So... How?
Please note that this is C++17 (some GCC flavor), which might not have some constexpr-related features that C++20 would have.
Other code requires that the function stays constexpr
.
I would like to avoid duplicating the function, if at all possible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以在另一个函数中移动错误消息创建:
demo
You might move the error message creation in another function:
Demo