我正在处理一个应用程序,需要读取 10 多个 CSV 文件(不同类型)作为输入。数据被读入容器——std::map
或者vector
。
以前每种类型都有自己的解析函数,我正在努力将其统一为单个模板化函数:以节省未来的代码维护并为损坏的文件提供统一的错误报告。
该函数读取每一行,辨别容器类型是否具有 a 的概念key
(如map
)并用于emplace
这些概念,以及emplace_back
其他(如vector
)。
对容器值类的唯一期望是它的构造函数可以从 CSV 行实例化。构造函数的任何异常都是致命错误——报告输入文件名和行号,然后程序退出:
try {
if constexpr (is_associative_container<Container>(NULL)) {
result->emplace(typename Container::key_type(
key, keylen), value);
} else {
result->emplace_back(value);
}
} catch (const std::exception &e) {
fprintf(stderr, "%s:%zd: %s\n", path, line, e.what());
goto failure;
}
这一切都有效,我很高兴——大约 75% 的 CSV 解析现在是由这个函数完成的。
我现在面临着 CSV 文件的剩余四分之一,这些文件不太简单:因为其中的某些行需要特殊处理,并且它们的内容不应该存储在容器中。
的构造函数如何value_type
向函数发出信号,表明它抛出的异常不应被视为致命的?一种方法是选择一个标准异常(std::bad_function_call
?)作为信号,但这意味着,所选择的异常一定不会意外发生——这是不可靠的......
还要别的吗?
问题编辑与撰写此答案重叠。原来的答案如下。
请注意,在当前代码中,您已经区分了从 继承的异常
std::exception
和不从 继承的异常std::exception
。好的风格是继承所有例外,std::exception
但现实通常是不同的。您可以引入一些要抛出的特殊类型的异常:
关于动态异常规范的旧答案......
正如评论中提到的,动态异常规范已从 C++17 中删除。
在 C++17 之前,抛出异常规范中未列出的异常的函数会执行以下操作(来自cppreference):
除非您知道可以从异常规范中接受的某些异常,否则没有出路,但通常您不知道这一点。我不知道在通用代码中推导出“允许的”异常。无论如何,该功能已被删除。从某种意义上说,抛出异常规范中未列出的异常已经是“致命的”,你不需要做额外的事情。
如果正常情况下该行不应该进入容器,那么这不是异常流,并且您不应该使用异常。该函数应该采用另一个参数:
Function<bool(RowData)> shouldInsertIntoContainer
好吧,根据我自己的倾向——以及@Eljay(评论)和@463035818_is_not_an_ai(接受的答案)的建议,我修改了代码: