我有这样的代码:
void function()
{
auto isOk=task(1);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(2);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(3);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(4);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(5);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(6);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(7);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(8);
if(!isOk)
{
return;
}
// more code here
auto isOk=task(9);
if(!isOk)
{
return;
}
}
应该注意的是我不能把它们放在一个循环中(我的代码与此类似但不完全是这个代码)
if块是非常难看的,我可能很难写如下:
#define TASK(x) {if(!task(x)) return;}
void function()
{
TASK(1);
// more code here
TASK(2);
// more code here
TASK(3);
// more code here
TASK(4);
// more code here
TASK(5);
// more code here
TASK(6);
// more code here
TASK(7);
// more code here
TASK(8);
// more code here
TASK(9);
}
我的问题是:
使用C ++ 11时有没有更好的方法呢?
此代码的问题是:
我无法轻松调试。
宏不在命名空间内,可能与其他宏冲突。
由于这里的大部分答案试图解决特定代码中的问题,当我在寻找通用解决方案时,我会询问与此代码相关的特定问题:
1-我可以使用lambda来模仿宏吗?
2-我可以使用constexpr来模仿宏吗?
3-以编译器友好的方式模仿MACRO的任何其他方式(与宏的结果相同)所以我可以轻松调试它们吗?
答案 0 :(得分:2)
void function() {
if (!task(1)) return;
// code here
if (!task(2)) return;
// more code here
if (!task(3)) return;
// more code here
}
这个小而紧,没有丑陋的大块。
如果task(1)
更大,您可以将return;
放在下一行缩进上。
答案 1 :(得分:1)
您可以选择使用异常代替使用普通return
,而不是只保留当前函数,而是查看所有函数,直到找到catch块为止。
这样的事情:
void tryTask(int i){
auto isOk=task(i);
if(!isOk)
{
throw std::runtime_error("Task failed: Nr. "+to_string(i));
}
}
function()
{
tryTask(1);
// more code here
tryTask(2);
// more code here
tryTask(3);
...
}
但是,如果其中一个任务失败,这会让您的函数抛出异常而不是返回。如果这不是您想要的,请使用try-catch块将其包围在函数内部,或者从第二个函数中调用它:
void callfunction(){
try{
function();
} catch (std::exception& e) {
//do whatever happens if the function failed, or nothing
}
}
如果你可以控制task()
函数,你也可以决定直接在这个函数中抛出异常,而不是返回一个bool。
如果你想确保你只捕获自己的异常,那么为此只写一个小类,只获取处理异常所需的信息(如果你不需要,那么空类就可以完成这项工作)和抛出/捕获你的类的实例。
答案 2 :(得分:0)
我会将代码执行btw调用任务放入向量中,然后运行循环:
const size_t steps = 9;
using ops = std::function<void()>;
std::vector<ops> vops(steps);
steps[0] = [] { /* some code here to execute after task 0 */ };
...
for( size_t i = 0; i < steps; ++i ) {
if( !task(i) ) return;
if( vops[i] ) (vops[i])();
}
答案 3 :(得分:0)
这是一个使用lambdas的快速而肮脏的方法。
假设这是你的任务功能:
#include <iostream>
/** Returns 0 on success; any other returned value is a failure */
int task(int arg)
{
std::cout << "Called task " << arg << std::endl;
return arg < 3 ? 0 : 1;
}
按如下方式调用链中的任务:
#include <iostream>
int main()
{
int result = Chain::start()
.and_then([]() -> int {return task(1);})
.and_then([]() -> int {return task(2);})
.and_then([]() -> int {return task(3);})
.and_then([]() -> int {return task(4);})
.and_then([]() -> int {return task(5);})
.and_then([]() -> int {return task(6);})
.and_then([]() -> int {return task(7);})
.and_then([]() -> int {return task(8);})
.and_then([]() -> int {return task(9);})
.result();
std::cout << "Chain result: " << result << std::endl;
return result;
}
因为只有在参数值小于3的情况下调用任务才会返回成功,所以调用链在第3步之后按预期停止:
$ ./monad
Called task 1
Called task 2
Called task 3
Chain result: 1
这是Chain类的实现:
class Chain
{
public:
const int kSuccess = 0;
Chain() {_result = kSuccess;}
static Chain start() { return Chain(); }
Chain& and_then(std::function<int()> nextfn) {
if(_result == 0) {
_result = nextfn();
}
return *this;
}
int result() { return _result; }
private:
int _result;
};
我知道,它看起来很丑陋而且非通用。但如果这是你想到的大方向,请告诉我,我们可以发展它。
答案 4 :(得分:0)
您可以使用整数序列。
task
此代码将扩展,就像您手动编写一样。
如果每个步骤的auto afterTask = std::make_tuple(
[](){ std::cout << "after task 0" << std::endl; },
[](){ std::cout << "after task 1" << std::endl; },
[](){ std::cout << "after task 2" << std::endl; },
[](){ std::cout << "after task 3" << std::endl; },
[](){ std::cout << "after task 4" << std::endl; },
[](){ std::cout << "after task 5" << std::endl; },
[](){ std::cout << "after task 6" << std::endl; },
[](){ std::cout << "after task 7" << std::endl; },
[](){ std::cout << "after task 8" << std::endl; },
[](){ std::cout << "after task 9" << std::endl; }
);
来电之间的代码不同,您可以使用元组。
function
然后使用:
更改template<std::size_t I, std::size_t... S>
bool function(std::index_sequence<I, S...>) {
return task(I) &&
(static_cast<void>(std::get<I>(afterTask)()), true) &&
function(std::index_sequence<S...>{});
}
的定义
{{1}}