我的任务是在C++类库中迁移错误处理的概念.之前简单返回bool(成功/失败)的方法应该被修改以返回一个Result传达机器可读错误代码和人类可读解释的对象(以及一些在这里无关紧要的解释).
遍历数千行代码是容易出错的,因此我尝试从编译器获得此任务的最佳支持.
我的结果类 - 在其他成员方法中 - 有一个构造函数,它构造了代码的结果和代码的赋值运算符:
class Result
{
public:
typedef unsigned long ResultCode;
explicit Result(ResultCode code); // (1)
Result& operator=(ResultCode code); // (2)
};
Run Code Online (Sandbox Code Playgroud)
备注:我通常会使用枚举类来ResultCode解决我的问题,但这不是一个选项.这是因为主要的设计目标是Result在不同的库中使用,每个库都应定义自己的结果代码集,而不需要一个大的头文件来定义所有库的所有可能的结果代码.实际上,每个类都应该能够定义本地结果代码,以便可以从类头中获得可能的结果代码列表.因此代码不能枚举Result,它们必须由使用Result类的类定义.
避免隐式转换
return true;
Run Code Online (Sandbox Code Playgroud)
客户端代码中的语句,构造函数已声明为显式.但是在嵌套方法调用中,会出现另一个问题.说,我有一个方法
bool doSomething()
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
我在一个返回一个Result对象的函数中使用它.我想转发嵌套调用的结果代码
Result doSomethingElse
{
Result result = doSomething();
return result;
}
Run Code Online (Sandbox Code Playgroud)
使用当前实现Result的赋值运算符,这不会给我一个编译器错误 - doSomething()的布尔返回值被隐式转换为unsigned long.
正如我在C++文档中所读到的,只有构造函数和转换运算符可以声明为显式.
我的问题
你的问题不在类中Result:毕竟你是显式地创建它的一个新实例;explicit不能禁止它。
我认为你不能禁止隐性晋升bool -> long。
你可以解决这个问题。一种方法是使其ResultCode 不是整数类型。那么,它可以有一个显式的构造函数。就像是
class ResultCode
{
unsigned long m_code;
public:
explicit ResultCode(unsigned long code) : m_code(code) {}
operator unsigned long () { return m_code; }
};
Run Code Online (Sandbox Code Playgroud)
将允许您在任何可以使用ResultCodea 的地方使用 aunsigned int并将其创建为ResultCode res = 5或return ResultCode(5)但不调用需要 a 的函数ResultCode(例如Result构造函数!)以及任何不是 a 的东西ResultCode,也不会执行诸如return 5函数必须返回 a 之类的操作ReturnCode。
否则,您可以使用模板重载来“捕获”任何不存在的内容unsigned int并强制其成为错误
typedef unsigned long ResultCode;
class Result
{
ResultCode m_par;
public:
template<typename T>
Result(T param) { static_assert(false); }
template<>
Result(ResultCode par): m_par(par) {}
};
int main()
{
ResultCode a = 5; //ok
//unsigned long a = 6; //also ok
//bool a = true; //error!
//int a = 7; //also error!!
Result b(a);
}
Run Code Online (Sandbox Code Playgroud)