技巧:回调的优雅写法

设想这样一个情景,在一个函数中,你需要去回调listener中的方法,在return前通知监听者。但这个函数的逻辑分支比较多,而且可能有多个分支都需要通知listener
示例:

void event::notify() {
	int32_t res;
	if (con1) {
		_listener->update(res);
		return;
	} else if (con2) {
		return;
	}

	// do some things. fill into res

	if (con3) {
		// do some things. modify res

		_listener->update(res);
		return;
	} else if (con4) {
		// do some things. modify res
		_listener->update(res);
		return;
	}

	
	return;
}

可以看到 _listener->update() 出现多次。这是很不优雅的写法,而且维护起来也比较困难。
提供一个更加优雅的写法:

void event::notify() {
	int32_t res;

	struct final_callback {

		final_callback(event* this, const int32_t& param) 
									: _this(this), _param(param){};
		~finnal_callback() {
			_this->_listener->update(_param);
		}
		
		event* _this;
		const int32_t& _param;
	} _final_callback(this, res);

	if (con1) {
		return;
	} else if (con2) {
		return;
	}

	// do some things. fill into res

	if (con3) {
		// do some things. modify res
		return;
	} else if (con4) {
		// do some things. modify res
		return;
	}

	return;
}

利用了RAII优雅地解决了return前的回调问题。
但这个方案存在一个很大的问题:示例代码中最后一个return是不需要回调的,但我们的“优雅写法”中,仍然产生了回调行为。
为了解决这个问题,可以加一个标记非法的标志位,listener在update中自行判断即可。