65.9K
CodeProject 正在变化。 阅读更多。
Home

Active 错误代码

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (10投票s)

2009年5月2日

CPOL

5分钟阅读

viewsIcon

29366

downloadIcon

120

一个确保错误代码得到检查而不是被忽略的机制。

动机

永恒的问题——是应该使用错误代码还是异常?两者都有各自的优势和劣势。异常不需要检查,但会使本地检查错误更加困难,并影响性能。

引入主动错误代码——错误代码返回的值会知道你是否已经检查过它们……如果你没有检查,那么它们就会抛出异常(如果它们指示了错误)。

教程

那么,什么是错误代码?对于主动错误代码而言,错误代码是一种任意类型的值,可以确定为“好”(不指示错误)或“坏”(指示错误)。例如,Win32 函数 CreateFile 在文件无法打开时返回预定义的 INVALID_HANDLE_VALUE 值,类型为 HANDLE。另一个例子是 CoCreateInstance,它返回一个 HRESULT。如果最高有效位被设置,这表示某种形式的失败,所以没有一个单一的“好”或“坏”值。在这种情况下,你可能需要某种函数来确定错误代码的状态。

因此,主动错误代码分为两类——一种是具有单一值来指示已发生(或未发生)错误状态的错误,另一种是使用函数来确定其状态的错误。

// Define and use an error code (of type int) that has a single 'good' value (0)
typedef ErrCodeWithGoodValue<int, 0> Err;
Err Test_Err(bool isGood)
{
   // Return the error's good value if isGood is true, some other value if false.
   int e = isGood?(Err::value):(Err::value+1);
   return Err(e);
}

// Define and use an error code (of type HRESULT) defined by a function (HRIsGood)
bool HRIsGood(HRESULT hr)
{
   return SUCCEEDED(hr);
}
typedef ErrCodeWithFn<HRESULT, &HRIsGood> eHRESULT;
eHRESULT Test_eHRESULT(bool isGood)
{
   return isGood?S_OK:E_UNEXPECTED;
}

这些错误代码值可以手动检查,也可以让它们抛出异常

void TestThrowOnError(bool b)
{
   // Will throw an exception when Test's return value
   // goes out of scope, i.e. at the end of the line
   Test_eHRESULT(b);
}

void TestHandleError(bool b)
{
   if (Test_Err(b).good())
   {
      std::cout << "Good\n";
   }
   else
   {
      std::cout << "Bad\n";
   }
}

如果使用了错误代码的异常抛出能力,那么错误值返回就不应该赋给一个变量——这将导致错误值的检查延迟到变量超出作用域,这可能是在执行依赖于可能出错的函数的功能之后。

用法

这个库由一个单独的头文件组成,ActiveErrors.h。这个头文件应该被需要定义错误代码类型的源文件#include。一般而言,这很可能会在声明函数签名(以及类定义内的)的头文件中。

参考

template <class ErrCodeType, bool (*IsGoodValueFn)(ErrCodeType)> class ErrCodeWithFn

模板类,它使用一个函数来确定错误值是否指示了一个错误条件。

模板参数

class ErrCodeType 

ErrCodeType 应该是一个可复制构造的类型。此外,由于该类型的值是通过值传递的,因此它应该是一个易于复制的类型。

bool (*IsGoodValueFn)(ErrCodeType) 

指向用于确定错误代码好坏的函数的指针。请注意,这不能是成员函数的指针。

方法

ErrCodeWithFn(ErrCodeType errorCode)
ErrCodeWithFn(ErrCodeWithFn const& other)
ErrCodeWithFn& operator=(ErrCodeWithFn const& other)

构造函数存储错误代码值并将其标记为未检查。复制构造函数和赋值运算符将源错误对象标记为已检查。

~ErrCodeWithFn()

析构函数将在其值指示错误且尚未检查时抛出异常。

bool good() const

good() 指示是否发生了错误。执行此方法会将错误代码标记为已检查。

operator ErrCodeType() const

此转换运算符允许检查错误代码的特定值。执行此方法会将错误代码标记为已检查。

template <class ErrCodeType, ErrCodeType GoodValue>
class ErrCodeWithGoodValue

模板类,对于错误代码类型,它有一个单一的“好”值。

模板参数

class ErrCodeType 

ErrCodeType 应该是一个整数类型。这对 ErrCodeWithFn 来说是一个更严格的约束,因为该类型的一个项被用作模板参数。

ErrCodeType GoodValue 

类型为 ErrCodeType 的值,这是该类型 ErrCodeType 的唯一“好”值。

方法

ErrCodeWithGoodValue(ErrCodeType errorCode)
ErrCodeWithGoodValue(ErrCodeWithGoodValue const& other)
ErrCodeWithGoodValue& operator=(ErrCodeWithGoodValue const& other)

构造函数存储错误代码值并将其标记为未检查。复制构造函数和赋值运算符将源错误对象标记为已检查。

~ErrCodeWithGoodValue()

析构函数将在其值指示错误且尚未检查时抛出异常。

bool good() const

good() 指示是否发生了错误。执行此方法会将错误代码标记为已检查。

operator ErrCodeType() const

此转换运算符允许检查错误代码的特定值。执行此方法会将错误代码标记为已检查。

template <class ErrCodeType, ErrCodeType BadValue> class ErrCodeWithBadValue

模板类,对于错误代码类型,它有一个单一的“坏”值。

模板参数

class ErrCodeType 

ErrCodeType 应该是一个整数类型。这对 ErrCodeWithFn 来说是一个更严格的约束,因为该类型的一个项被用作模板参数。

ErrCodeType BadValue 

类型为 ErrCodeType 的值,这是该类型 ErrCodeType 的唯一“坏”值。

方法

ErrCodeWithBadValue(ErrCodeType errorCode)
ErrCodeWithBadValue(ErrCodeWithBadValue const& other)
ErrCodeWithBadValue& operator=(ErrCodeWithBadValue const& other)

构造函数存储错误代码值并将其标记为未检查。复制构造函数和赋值运算符将源错误对象标记为已检查。

~ErrCodeWithBadValue()

析构函数将在其值指示错误且尚未检查时抛出异常。

bool good() const

good() 指示是否发生了错误。执行此方法会将错误代码标记为已检查。

operator ErrCodeType() const

此转换运算符允许检查错误代码的特定值。

与其他错误代码类不同,此运算符将在值是“坏”的且在调用此运算符之前尚未检查其有效性时抛出异常。这是因为这种类型的返回值很可能返回一些可供您使用的资源,因此在检查值后再使用它比其他错误代码类型更容易发生。

这种资源的一个例子是从内存分配例程返回的指针,该指针在不是 null 时是“好”的。

class UncheckedErrorBase

所有当未检查的“坏”错误类被销毁时抛出的异常的基类。

template <class ErrCodeType> class UncheckedError;

模板类;当未检查的“坏”错误类被销毁时抛出的异常。此类派生自 UncheckedErrorBase,以便任何未检查的错误都可以用单个 catch 处理程序捕获。

模板参数

class ErrCodeType 

底层错误值的类型。

历史

  • 2009年5月1日:初始版本
© . All rights reserved.