了解 <system_error> C++11 中的设施
Understanding the <system_error> facility in C++11
我正在尝试使用system_error
工具来处理我的库中的错误。我将简要讨论库的结构,以防您发现它有帮助:库的名称空间称为commons
,在此名称空间下,我有另一个名称空间dynlib
。dynlib
包含负责加载.so/.dll文件的类:
namespace commons {
namespace dynlib {
class DynLibLoader {
};
}
}
DynLibLoader中可能出现的错误为LibraryFailedToLoad
、LibraryFailedToUnload
和SymbolNotFound
。因此,我对处理错误的想法如下:我将在名称空间dynlib
下添加一个名称空间error
。然后,在该名称空间下,我将为std::error_codes
定义一个枚举,为std::error_conditions
定义一个enum。根据我的理解,std::error_codes
必须对应于errno
(Linux)或GetLastError
(Win32)的值,而std::error_conditions
必须对应于像LibraryFailedToLoad
、SymbolNotFound
等的值。因此,以下是我的问题:
- 我对
std::error_code
和std::error_condition
的理解正确吗 - 我应该如何知道
errno
和GetLastError()
的所有可能值,以便在我的std::error_codes
枚举下定义它们?如果Microsoft将来在API中添加额外的错误值会怎样?我是否必须回到源代码,并在std::error_codes
的枚举下定义它们 - 如果我们在另一个平台上,当发生错误时,无法找出确切的系统错误代码,该怎么办
- 如果我想对整个commons命名空间使用相同的
std::error_codes
,而只为每个子命名空间定义不同的std::error_condition
(如dynlib
),该怎么办。这是个好做法吗?我会答应,因为这样可以避免重复代码。但这背后有陷阱吗 - 目前,我正在为commons的每个子命名空间使用一个
std::error_category
。这是个好做法吗?你认为我应该以不同的方式使用std::error_category
吗
主要区别在于std::error_condition
是可移植的(独立于平台),而std::error_code
是依赖于平台的。通常,低级平台相关代码生成error_codes
,客户端代码将这些error_codes
与平台无关的error_conditions
进行比较。
19.5[syserr]定义了与errno
(例如ENOENT
)的特定值显式关联的标准(和可移植)错误条件(例如,errc::no_such_file_or_directory
)的长列表。因此,您不需要知道系统上生成的errno
或GetLastError()
的可能值的完整列表。您只需要知道与代码相关的标准值。例如,您的库实现可能如下所示:
void MyLibraryClass::foo(std::error_code &ec)
{
// whatever platform dependent operation that might set errno
// possibly with alternative platform-dependent implementations
ec = make_error_code(errno);
}
然后,您的客户端代码将检查error_code
是否与任何特定的error_condition
:匹配
error_code ec;
myLibraryInstance.foo(ec);
if (!ec)
{
// success
}
else if (errc::no_such_file_or_directory == ec)
{
// no_such_file_or_directory
}
else
{
// unknown or unexpected error
}
在您的情况下,您可能会定义自己的错误枚举(只有一个枚举),并将其标记为error_conditions
以启用自动转换:
namespace commons
{
namespace dynlib
{
enum class errc {LibraryFailedToLoad=1, LibraryFailedToUnload, SymbolNotFound};
}
}
namespace std
{
template<> struct is_error_condition_enum<commons::dynlib::errc> : true_type {};
}
// TODO: implement make_error_code and make_error_condition
然后,您可以将各种平台相关操作的结果转换为适当的error_condition
(或者error_code
,如果您愿意的话):
void DynLibLoader::open(std::error_code &ec)
{
// possibly implement the windows version here as well
if (NULL == dlopen(filename, flag))
{
ec = make_error_code(errc::LibraryFailedToLoad);
}
}
您的客户端代码会将错误代码与可能的错误条件进行比较,如上所述:
error_code ec;
dynLibLoader.open(ec);
if (!ec)
{
// success
}
else if (commons::dynlib::errc::LibraryFailedToLoad == ec)
{
// Library Failed To Load
}
else
{
// unknown or unexpected error
}
注意,枚举commons::dynlib::errc::LibraryFailedToLoad
被自动转换为error_condition
(使用所提供的make_error_condition
方法),因为commons::dynlib::errc
被is_error_condition_enum
标记。
error_category
到名称空间的映射可能是个人偏好,但这似乎有点人为。在这种特定情况下,为dynlib
名称空间指定一个类别确实是有意义的,但很容易找到将类别分布在多个名称空间中有意义的示例。在某些情况下,将所有不同的错误枚举都放在一个唯一的命名空间(例如commons::errors
)中可能是有意义和实用的。
- MSVC是否支持C++11样式的属性而不是__declspec
- 创建LinkedList退出,返回代码为-11(SIGSEGV)
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如何将模板转换为C++11之前的模板
- EASTL矢量<向量<int>>连续的
- c++11评估顺序(未定义的行为)
- C++中的VLA,扩展名为std=C++11
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- "类模板示例<int>;"语句对 C++11 是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 如何使用lock_guard在c++11中实现scoped_lock功能
- C++11 中不同类型的对象的 std::array 的替代方案
- 为什么 -mmacosx-version-min=10.10 不阻止使用标记为从 10.11 开始的函数?
- 为什么我的C++代码中出现'Segmentation Fault: 11'行?
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- STLPort using C++11
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy