假设我有constexpr
数据集。我主要在编译时使用它,它存储可能影响未来constexpr
语句的设置的数据。string_view
允许我命名这些设置并轻松地搜索它们:
struct data {
std::string_view name;
int value;
};
constexpr auto data_set = std::array{
data{"foo", 100},
data{"bar", 200},
};
这是一个constexpr
函数,它允许我找到数据点并返回它们的值:
constexpr int get_data(std::string_view search) {
for (auto& data : data_set) {
if (data.name == search) {
return data.value;
}
}
}
当我用正确的字符串名和不正确的字符串名称调用这个函数时,这种方法工作得很好。因为如果它找不到name
,则该函数没有返回语句,因此无法初始化constexpr
值:
int main() {
constexpr auto foo = get_data("foo");
constexpr auto foo2 = get_data("foo2"); //Error C2131: expression did not evaluate to a constant
}
我的IDE (Visual )甚至给了我一个很好的可见活动错误:
Error (active) E0028 expression must have a constant value
但是,在使用此命令并对其进行非参数调用时,我总是会收到警告。
warning C4715: 'get_data': not all control paths return a value
显然,我不能添加一个默认的返回值,因为这不符合"constexpr
fails (如果无效)“的目的,但我仍然希望能够用它初始化运行时变量(因为在编译时仍然知道搜索string_view,这样做是安全的)。
那么,是否有一种方法可以对无效输入保留此错误,但删除该错误?你也能让这个函数不返回任何东西吗?
发布于 2022-05-11 10:57:47
consteval
将启用此行为。因此,任何以这种方式标记的函数都必须在编译时进行计算。这也将删除警告,因为如果它没有正确计算,它将被错误所取代。
consteval int get_data(std::string_view search) {
for (auto& data : data_set) {
if (data.name == search) {
return data.value;
}
}
}
int main() {
constexpr auto foo = get_data("foo");
constexpr auto foo2 = get_data("foo2");
}
"foo2"
行导致C2131和active error E3133:
Error C2131 expression did not evaluate to a constant
Error (active) E3133 call to consteval function "get_data" did not produce a valid constant expression
您仍然可以使用它初始化运行时变量:
auto bar = get_data("bar");
因为get_data
可以在编译时被计算,并且基本上被data{ "bar", 200 }.value;
所取代,或者只是200
。
现在,consteval
将使纯运行时调用不再工作(比如从std::cin
输入或文件中读取搜索项),但这是所需的行为,因为理论上,如果输入无效,则可能导致未指定的分支。
,您也可以让这个函数不返回任何东西吗?
如果到达,可以在应该失败的分支中添加无效的语句。例如,1 / 0
consteval void check_data(std::string_view search) {
for (auto& data : data_set) {
if (data.name == search) {
return;
}
}
auto invalid = 1 / 0;
}
int main() {
check_data("foo");
check_data("bar");
check_data("bar2"); //E3133 active error
}
@GoswinvonBrederlow建议抛出异常,这也非常有效,甚至比1 / 0
更干净,在我看来:
consteval auto get_data(std::string_view search) {
for (auto& data : data_set) {
if (data.name == search) {
return data.value;
}
}
throw std::exception("fail");
}
consteval void check_data(std::string_view search) {
for (auto& data : data_set) {
if (data.name == search) {
return;
}
}
throw std::exception("fail");
}
int main() {
constexpr auto foo = get_data("foo");
constexpr auto foo2 = get_data("foo2"); //E3133 active error
auto bar2 = get_data("foo2"); //E3133 active error
check_data("foo");
check_data("foo2"); //E3133 active error
}
发布于 2022-05-11 11:19:51
我知道可以有许多优雅的解决方案,但我建议的只是在函数的末尾添加一个无条件的返回。
constexpr int get_data(std::string_view search) {
for (auto& data : data_set) {
if (data.name == search) {
return data.value;
}
}
return -1;
}
https://stackoverflow.com/questions/72199810
复制相似问题