可选参数常量引用重新分配

Optional parameter const reference reassignment

本文关键字:分配 新分配 参数 常量 引用      更新时间:2023-10-16

我知道这是不可能的,因为我正在打破常量收缩的心脏,我不允许以任何方式修改对象,但是我如何选择传递参数作为引用?

假设我有一个错误代码结构和一些成员函数,我可以选择检查的错误代码

struct my_error_code {
    int val;
    std::string message;
};

struct my_complicated_obj {
    /* Compiles fine, understandbly, ec is not optional*/
    void do_stuff(/*params,*/my_error_code& ec){
        ec = {0x10, "Something went wrong"};
        return;
    }
    void do_stuff_optionally(/*params,*/ const my_error_code& ec= {}){
        /* There is no overload of assignment or constructos I can trick into allowing this.. */
        ec = {0x20, "Something is wrong."};
        return;
    }
};

在上面的do_stuff_optionally显然不会编译。我当时所知道的解决方案是

my_error_code& my_error_code_default(){
    static my_error_code ec = {0, "No Error"};
    return ec;
}
void do_stuff_optionally_not_so_very_clean(/*params,*/ my_error_code& ec = my_error_code_default()){
        ec = {0x11, "Something went wrong."};
    }

但顾名思义,这不是很干净,为了保留一个全局对象(本质上(,这样我就可以通过引用将我的类型用作可选的可变参数。

我尝试研究 boost 是如何用 boost::system::error_code 做到这一点的,但我在那里找不到任何静态对象,那么 boost 是如何做到这一点的呢?什么是清洁方法?

你可以用手写出重载:

void do_stuff_optionally(/*params,*/ my_error_code& ec);
void do_stuff_optionally(/*params */) {
    my_error_code ec;
    do_stuff_optionally(/*params,*/ ec);
}

也就是说,如果你的函数没有返回任何内容,你可以直接返回更干净的错误代码。如果它返回其他内容,您可以返回对象或带有boost::variant的错误代码。

最后,你应该知道,由于你使用的是 boost,boost 经常使用这种重载约定,错误代码通过引用传递而不是不传递,意思是:如果你没有传入错误代码,那么抛出来指示错误。您使用相同的约定来表示(afaics(忽略错误,这可能有点风险(我认为(。

去掉const,并使用指针而不是引用:

struct my_complicated_obj {
    void do_stuff(/*params,*/my_error_code& ec){
        do_stuff_optionally(/*params,*/ &ec);
    }
    void do_stuff_optionally(/*params,*/ my_error_code *ec = nullptr){
        if (ec)
            *ec = {0x20, "Something is wrong."};
    }
};

让调用方决定是否需要错误代码。