C++ 如何在没有大量重复检查代码的情况下处理函数的多个可能的早期返回
鉴于我不想在此代码中使用异常,如何删除重复的:C++ 如何在没有大量重复检查代码的情况下处理函数的多个可能的早期返回,c++,return,early-return,C++,Return,Early Return,鉴于我不想在此代码中使用异常,如何删除重复的: if(rc!=SQLITE\u确定){ 返回rc; } 在下面这个函数中的大多数语句之后检查 int sqlite::update(const std::string&table_name,const std::vector&fields,const std::vector&where){ if(db_==nullptr){ 返回SQLITE_错误; } const std::string sql=update\u helper(表名称、字段,其
if(rc!=SQLITE\u确定){
返回rc;
}
在下面这个函数中的大多数语句之后检查
int sqlite::update(const std::string&table_name,const std::vector&fields,const std::vector&where){
if(db_==nullptr){
返回SQLITE_错误;
}
const std::string sql=update\u helper(表名称、字段,其中);
sqlite3_stmt*stmt=NULL;
int rc=sqlite3\u prepare\u v2(db\uu,sql.c\u str(),-1,&stmt,NULL);
如果(rc!=SQLITE_OK){
返回rc;
}
//循环遍历每个参数,为每个参数调用bind
rc=绑定字段(stmt,字段);
如果(rc!=SQLITE_OK){
返回rc;
}
//循环遍历每个where参数,为每个参数调用bind
rc=绑定_where(stmt,where);
如果(rc!=SQLITE_OK){
返回rc;
}
返回步骤和最终确定(stmt);
}
您可以使用lambda和if初始值设定项表达式来清除代码,但仍然必须返回错误代码:
int sqlite::update(const std::string&table_name,const std::vector&fields,const std::vector&where){
if(db_==nullptr){
返回SQLITE_错误;
}
const std::string sql=update\u helper(表名称、字段,其中);
sqlite3_stmt*stmt=NULL;
const auto validate_sql=[](int rc)->bool{
返回rc!=SQLITE\u OK;
};
if(int rc=sqlite3\u prepare\u v2(db\u0,sql.c\u str(),-1,&stmt,NULL);验证\u sql(rc)){
返回rc;
}
//循环遍历每个参数,为每个参数调用bind
if(int rc=bind_fields(stmt,fields);validate_sql(rc)){
返回rc;
}
//循环遍历每个where参数,为每个参数调用bind
if(int rc=bind_where(stmt,where);validate_sql(rc)){
返回rc;
}
返回步骤和最终确定(stmt);
}
通过外部工作,可以编写一元版本
伪代码如下所示:
expected<void, RC> doStuff( arg1, arg2 ){
auto a = op1(arg1, arg2 );
return a->*op2(arg2)->*op3(arg1);
}
预期剂量(arg1、arg2){
自动a=op1(arg1,arg2);
返回一个->*op2(arg2)->*op3(arg1);
}
或
预期剂量(arg1、arg2){
自动a=co_等待op1(arg1);
返回op2(co_等待op3(arg2),co_等待op4(arg1,arg2));
}
但是函数外部的样板远远超过函数内部删除的样板
最后,有人提议增加零成本例外
如果希望控制流不要求您键入控制流,则这些和宏是关于您的选项
对于预期的情况,我们的想法是,当您对其执行->*
操作时,预期的错误不会调用该操作,而只是通过错误状态
它是一种没有异常的手动异常形式,但是如果在使用点或包装特定于操作集的代码时没有更多的样板文件,就无法自动化样板文件
协同程序1具有不可避免的分配开销(好吧,您的代码无法避免;理论上编译器可以避免),以及一些最神秘的隐藏代码。同样,这里我们试图在没有异常的情况下伪造类似异常的语法;co_在收到错误时等待,将其传递给返回值
TL;DR是“不,你不能摆脱控制流样板文件”。首先,如果出现问题,你正在泄漏sqlite3\u stmt
。在返回任何内容之前,需要调用sqlite3\u finalize()
对于您的问题,您可以将重复的if..return
s包装在预处理器宏中,例如:
#定义检查(RC)\
如果(rc!=SQLITE_OK)\
{ \
sqlite3_最终确定(stmt)\
返回rc\
}
int sqlite::update(const std::string&table_name,const std::vector&fields,const std::vector&where){
if(db_==nullptr){
返回SQLITE_错误;
}
const std::string sql=update\u helper(表名称、字段,其中);
sqlite3_stmt*stmt=NULL;
int rc=sqlite3\u prepare\u v2(db\uu,sql.c\u str(),-1,&stmt,NULL);
检查_RC(RC);
//循环遍历每个参数,为每个参数调用bind
rc=绑定字段(stmt,字段);
检查_RC(RC);
//循环遍历每个where参数,为每个参数调用bind
rc=绑定_where(stmt,where);
检查_RC(RC);
返回步骤和最终确定(stmt);
}
或者:
#定义检查(op)\
{ \
int rc=op\
如果(rc!=SQLITE_OK)\
{ \
sqlite3_最终确定(stmt)\
返回rc\
} \
}
int sqlite::update(const std::string&table_name,const std::vector&fields,const std::vector&where){
if(db_==nullptr){
返回SQLITE_错误;
}
const std::string sql=update\u helper(表名称、字段,其中);
sqlite3_stmt*stmt=NULL;
检查_RC(sqlite3_prepare_v2(db_,sql.c_str(),-1,&stmt,NULL));
//循环遍历每个参数,为每个参数调用bind
检查_RC(绑定_字段(stmt,字段));
//循环遍历每个where参数,为每个参数调用bind
检查_RC(绑定_where(stmt,where));
返回步骤和最终确定(stmt);
}
或者,您可以重新编写代码以不使用多个return
s,例如:
int sqlite::update(const std::string&table_name,const std::vector&fields,const std::vector&where){
int rc;
if(db_==nullptr){
rc=SQLITE_错误;
}
否则{
const std::string sql=update\u helper(表名称、字段,其中);
sqlite3_stmt*stmt=NULL;
rc=sqlite3\u prepare\u v2(db\u,sql.c\u str(),-1,&stmt,NULL);
如果(rc==SQLITE_OK){
//循环遍历每个参数,为每个参数调用bind
rc=绑定字段(stmt,字段);
如果(rc==SQLITE_OK){
//循环遍历每个where参数,为每个参数调用bind
rc=bind\u w
expected<void,RC> doStuff(arg1,arg2){
auto a = co_await op1(arg1);
return op2( co_await op3(arg2), co_await op4(arg1, arg2) );
}
int sqlite::update(
const std::string& table_name,
const std::vector<column_values>& fields,
const std::vector<column_values>& where
) {
sqlite3_stmt* stmt = NULL;
int rc = SQLITE_ERROR;
if (db_ != nullptr) {
const std::string sql = update_helper(table_name, fields, where);
rc = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, NULL);
}
if (rc == SQLITE_OK) {
// loop thru each parameter, calling bind for each one
rc = bind_fields(stmt, fields);
}
if (rc == SQLITE_OK) {
// loop thru each where parameter, calling bind for each one
rc = bind_where(stmt, where);
}
if (rc == SQLITE_OK) {
rc = step_and_finalise(stmt);
}
return rc;
}