在 consteval 时提供 constexpr 安全的简化异常消息,否则提供 stringstream 详细信息
Provide constexpr-safe simplified exception message when consteval'd, otherwise stringstream verbose info
想象一下这个简单的 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():你做错了。”
好的,这不是很有帮助,我想创建一个更好的错误消息:
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];
}
但这是不允许的:“不能在 constexpr 函数中定义非文字类型 'std::stringstream'(又名 'basic_stringstream')的变量”。
对于编译时版本,我可以接受更简单的错误消息,并且只在 运行-time 版本中进行复杂的字符串操作。
所以...如何?
请注意,这是 C++17(一些 GCC 风格),它可能没有 C++20 所具有的一些与 constexpr 相关的特性。
其他代码要求函数保持constexpr
.
如果可能的话,我想避免重复该功能。
您可以将错误消息创建移动到另一个函数中:
std::string get_error_message(int index, int length = 10)
{
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 << ").";
return stream.str();
}
constexpr float getItem(int index)
{
constexpr int length = 10;
constexpr std::array<float, length> items{};
if (index < 0 || index >= length)
{
throw std::runtime_error(get_error_message(index, length));
}
return items[index];
}
想象一下这个简单的 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():你做错了。”
好的,这不是很有帮助,我想创建一个更好的错误消息:
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];
}
但这是不允许的:“不能在 constexpr 函数中定义非文字类型 'std::stringstream'(又名 'basic_stringstream')的变量”。
对于编译时版本,我可以接受更简单的错误消息,并且只在 运行-time 版本中进行复杂的字符串操作。
所以...如何?
请注意,这是 C++17(一些 GCC 风格),它可能没有 C++20 所具有的一些与 constexpr 相关的特性。
其他代码要求函数保持constexpr
.
如果可能的话,我想避免重复该功能。
您可以将错误消息创建移动到另一个函数中:
std::string get_error_message(int index, int length = 10)
{
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 << ").";
return stream.str();
}
constexpr float getItem(int index)
{
constexpr int length = 10;
constexpr std::array<float, length> items{};
if (index < 0 || index >= length)
{
throw std::runtime_error(get_error_message(index, length));
}
return items[index];
}