C++:我可以使赋值运算符"显式"

kri*_*_sw 6 c++

我的任务是在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++文档中所读到的,只有构造函数和转换运算符可以声明为显式.

我的问题

  1. 为什么显式不允许赋值运算符或其他方法?IMO将允许任何方法显式化也很有意义.
  2. 是否有其他解决方案可以防止赋值运算符的隐式类型转换?

Fra*_*ndi 4

你的问题不在类中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 = 5return 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)